【问题标题】:react native and recoil multiple re-renders of RecoilRoot对 RecoilRoot 的多次重新渲染做出本机反应并反冲
【发布时间】:2021-08-19 22:01:33
【问题描述】:

我的这些组件没有任何反冲钩。

const C = () => {
  console.log('---->C')
  return <Text>C</Text>
}
const B = () => {
  console.log('--->B')
  return <>
    <Text>B</Text>
    <C/>
  </>
}
const A = () => {
  console.log('-->A')
  return <>
    <Text>A</Text>
    <B/>
  </>
}

const App = () => {
  console.log('->App')
  return (
    <RecoilRoot>
      <A />
    </RecoilRoot>
  );
};

当我在控制台中运行应用程序时,会显示指定的日志:

 LOG  ->App
 LOG  -->A
 LOG  --->B
 LOG  ---->C

现在我将使用反冲钩子来改变和访问原子状态

import { atom, useSetRecoilState, useRecoilState, useRecoilValue, RecoilRoot } from "recoil";
const atomTest = atom({
  key: "abcatomTest",
  default: "A"
})
const C = () => {
  console.log('---->C')
  const [value, set] = useRecoilState(atomTest)
  return <>
    <Text>C</Text>
    
  </>
}
const B = () => {
  console.log('--->B')
  const set = useSetRecoilState(atomTest)

  return <>
    <Text>B</Text>
    <C/>
  </>
}
const A = () => {
  console.log('-->A')
  const value = useRecoilValue(atomTest)
  
  return <>
    <Text>A</Text>
    <B/>
  </>
}

const App = () => {
  console.log('->App')
  return (
    <RecoilRoot>
      <A />
    </RecoilRoot>
  );
};

我什至不使用从useRecoilValueuseSetRecoilStateuseRecoilState 返回的值和函数,如果我使用它,它可以正常工作,但在第一次渲染时,日志是:

 LOG  ->App
 LOG  -->A
 LOG  -->A
 LOG  ->App
 LOG  --->B
 LOG  ---->C
 LOG  ---->C
 LOG  --->B
 LOG  -->A
 LOG  ->App
 LOG  -->A
 LOG  --->B
 LOG  ---->C

为什么recoil会强制重新渲染包括root在内的多个组件,我根本没有改变状态,并且在App组件中也不依赖于任何状态!

【问题讨论】:

    标签: react-native state-management recoiljs


    【解决方案1】:

    首先:React 执行一个函数并不意味着组件实际上会重新渲染。 React 有一个提交和一个渲染阶段。在提交阶段,React 会进行更改并调用子组件,检查是否有任何新内容要渲染。在渲染阶段,React 检查是否有组件需要重新渲染。如果输出、钩子状态和道具相同,则不会重新渲染,即使 React 之前调用了您的函数组件。这就是您看到所有日志的原因。您不是检查重新渲染,而是检查函数执行。

    您的 App 组件实际上具有要声明的依赖项,因为它呈现 RecoilRoot 组件。当该组件发生变化时,React 将再次进入提交阶段并遍历所有子组件,以查看是否有更改。

    由于每个组件都使用引用 atomTest 原子的挂钩,因此 Recoil 必须为该组件订阅该原子。所以 Recoil 和 React 必须通过树来寻找变化。

    如果您检查 React 开发者工具的 Profiler,您会发现没有实际的重新渲染,因为您的组件没有更改任何输出。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-14
      • 2022-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多