0

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

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>
  );
};

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

 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

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

4

1 回答 1

1

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

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

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

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

于 2021-06-01T19:05:49.720 回答