对 RecoilRoot

问题描述

我有这些组件,没有任何后坐钩。

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

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

解决方法

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

您的 App 组件实际上依赖于状态,因为它呈现 RecoilRoot 组件。当那个组件发生变化时,React 会再次进入提交阶段并遍历所有子组件,看看是否有变化。

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

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

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...