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

标签 javascript reactjs

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

这是我所做的。

  1. 创建了一个上下文,然后创建了一个呈现其提供程序的组件。
  2. 提供者提供状态值及其 setter 。
  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>;
}

两个 child

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

应用程序

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

这是一个codesandbox demo

最佳答案

找到原因了,

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

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

搜索了codesandbox存储库问题,发现它与严格模式下的 react 行为相关:

It is expected that setState updaters will run twice in strict mode in development. This helps ensure the code doesn't rely on them running a single time (which wouldn't be the case if an async render was aborted and alter restarted). If your setState updaters are pure functions (as they should be) then this shouldn't affect the logic of your application.

Codesandbox issue

React issue

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

编辑

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

关于javascript - 为什么 React 上下文提供者组件渲染两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61532814/

相关文章:

reactjs - JestJS -> 不变违规 : Could not find "store" in either the context or props of "Connect(Portfolio)"

javascript - 从 axios 响应 reactjs 填充输入字段

javascript - 使用 JavaScript 验证 HTML 表单

javascript - 如何解析包含存储在变量中的 json 数据的 JavaScript 文件?

javascript - 悬停在图像上时添加 div 元素类

node.js - 在 axios.delete() 上获取 404(未找到)

reactjs - NextJS 来自字符串的头部

javascript - 为什么 chrome.pageCapture.saveAsMHTML 在我的 Google Chrome 扩展程序中不起作用?

javascript - 字符串替换不会替换字符的第二个实例

reactjs - 如何在 react 中注销