为什么 React 上下文提供者组件渲染两次

Moh*_*ADI 3 javascript reactjs

我正在使用 React Context API,发现提供程序在每次值更改时都会渲染两次。

这是我所做的。

  1. 创建了一个上下文,然后创建了一个呈现其提供者的组件。
  2. 提供者提供状态值及其设置器。
  3. 创建了一个直接渲染其子级的直接子级。
  4. 创建了一个读取上下文值并添加一个按钮来更改它的消费者。
  5. 每个组件在渲染时都会执行 console.log。
  6. 向提供程序添加了效果,无需每次渲染时都进行记录。
  7. 在提供程序中添加了一个引用,该引用在每次渲染时都会递增,并且会记录在渲染和效果中。

问题 ?

每次我点击按钮更改上下文值时,提供程序都会渲染两次,但效果仅执行一次。

因此 ref 总是递增两次,但效果每次只获取最后一个值(它会跳过一个值!)。

另外,在提供程序的第一次渲染时,它会记录两次相同的引用值,这对我来说非常奇怪。

谁能告诉我为什么我会出现这种行为?

这是代码:

提供者:

const MyContext = React.createContext(0);

function Provider({ children }) {
  const state = React.useState("Yes");
  const ref = React.useRef(0);
  ref.current += 1;
  console.log("Context provider ", ref.current);
  React.useEffect(() => {
    console.log("effect on provider, ref value = ", ref.current);
  });

  return <MyContext.Provider value={state}>{children}</MyContext.Provider>;
}
Run Code Online (Sandbox Code Playgroud)

两个孩子

function DirectChild({ children }) {
  console.log("provider direct child");
  return children;
}

function Consumer() {
  console.log("consumer");
  const [state, setState] = React.useContext(MyContext);
  return (
    <div>
      <span>State value: {state}</span>
      <br />
      <button onClick={() => setState(old => old + "Yes")}>Change</button>
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

该应用程序

export default function App() {
  console.log("APP");
  return (
    <Provider>
      <DirectChild>
        <Consumer />
      </DirectChild>
    </Provider>
  );
}
Run Code Online (Sandbox Code Playgroud)

这是一个codesandbox演示

Moh*_*ADI 6

找到原因了,

没有错误,也没有奇怪的行为,我只是错过了默认情况下codesandbox在React.StrictMode父级中渲染应用程序的情况。

首先,我将代码移植到本地项目中,然后发现没有问题。

搜索了codesandbox repo问题,发现它与严格模式下的反应行为相关:

预计 setState 更新程序将在开发中以严格模式运行两次。这有助于确保代码不依赖于它们运行一次(如果异步渲染被中止并更改重新启动,则不会出现这种情况)。如果您的 setState 更新程序是纯函数(它们应该是),那么这不应该影响您的应用程序的逻辑。

代码沙箱问题

反应问题

但是,该效果仅执行一次并且错过了我的参考更新。

编辑

React 18引入了严格效果,在开发过程中在严格模式下也运行了两次效果。