有人可以向我解释为什么下一个代码会重新渲染来自提供者的所有子组件
import { createContext, useContext, useState } from "react";
const ThemeContext = createContext();
const App = () => {
const [theme, setTheme] = useState(false);
console.log("App running");
return (
<ThemeContext.Provider value={{ theme, setTheme }} children={<Child1 />} />
);
};
const Child1 = () => {
console.log("Child1 running");
return (
<div className="child1">
<Child2 />
</div>
);
};
const Child2 = () => {
console.log("Child2 running");
return (
<div className="child2">
<Child3 />
</div>
);
};
const Child3 = () => {
const { theme, setTheme } = useContext(ThemeContext);
console.log("Child3 running");
return (
<div className="child3">
<p>{theme ? "dark" : "light"}</p>
<button onClick={() => setTheme(!theme)}>Change theme</button>
</div>
);
};
export default App;
控制台每次点击按钮,所有组件重新渲染App running
Child1 running
Child2 running
Child3 running
App running
Child1 running
Child2 running
Child3 running
但是如果上下文提供程序被包装在一个组件中,如下所示import { createContext, useContext, useState } from "react";
const ThemeContext = createContext();
const ThemeProvider = ({ children }) => {
const [theme, setTheme] = useState(false);
console.log("ThemeProvider running");
return (
<ThemeContext.Provider value={{ theme, setTheme }} children={children} />
);
};
const App = () => {
console.log("App running");
return <ThemeProvider children={<Child1 />} />;
};
const Child1 = () => {
console.log("Child1 running");
return (
<div className="child1">
<Child2 />
</div>
);
};
const Child2 = () => {
console.log("Child2 running");
return (
<div className="child2">
<Child3 />
</div>
);
};
const Child3 = () => {
const { theme, setTheme } = useContext(ThemeContext);
console.log("Child3 running");
return (
<div className="child3">
<p>{theme ? "dark" : "light"}</p>
<button onClick={() => setTheme(!theme)}>Change theme</button>
</div>
);
};
export default App;
单击按钮时的控制台ThemeProvider running
Child3 running
ThemeProvider running
Child3 running
ThemeProvider running
Child3 running
只有使用上下文的组件(和组件上下文提供者)正在重新渲染react 究竟是如何管理这种情况的
编辑:
react 版本是 17.0.1 btw
最佳答案
发生这种情况是因为 <Context.Provider>
当它的子节点支持 时重新渲染不共享引用相等 与以前的 child Prop 。
在第一个示例中,每次 App
被重新渲染,一个 新 Child1
创建 react 元素。
基本上就像你在做这样的事情:
const App = () => {
const [theme, setTheme] = useState(false);
console.log("App running");
return React.createElement(ThemeContext.Provider, {
value: {
theme: theme,
setTheme: setTheme
},
children: React.createElement(Child1, null) <= Notice how the children prop is new with every re-render
});
};
最终重新渲染 Child1
, Child2
和 Child3
.在第二个示例中,React 元素
Child1
在 App
内创建一次, 它被传递给 ThemeProvider
, 这意味着在 ThemeProvider
您实际上是在引用 相同 react 元素,并且不会在每次重新渲染时创建一个新元素,因此在这种情况下,只有关联的消费者组件( Child3
)会重新渲染。Good read about why this happens
关于javascript - React Context Provider 所有子级重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65638750/