【发布时间】:2020-08-15 08:55:59
【问题描述】:
我在玩 React Context API,发现提供程序在每次值更改时呈现两次。
这就是我所做的。
- 创建了一个上下文,然后是一个呈现其提供者的组件。
- 提供程序提供状态值及其设置器。
- 创建了一个直接渲染其子级的直接子级。
- 创建了一个消费者,它读取上下文值并添加一个按钮来更改它。
- 每个组件在呈现时都会执行一个 console.log。
- 为提供程序添加了一个效果,无需在每次呈现时都记录日志。
- 在提供程序中添加了一个 ref,该 ref 在每次渲染时递增,并在渲染和效果中记录。
问题?
每次点击按钮更改上下文值时,提供程序渲染两次,但效果只执行一次。
所以 ref 总是递增两次,但效果每次只获取最后一个值(它跳过一个值!)。
此外,在提供程序的第一次渲染时,它会记录两次相同的 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>;
}
两个孩子
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>
);
}
【问题讨论】:
-
将状态逻辑移到应用层,现在行为也在
App,渲染两次,记录两次,只有一个效果,这里是a demo -
我的理解是 refs 用于引用 Dom 对象,而不是 state refs(即
useState)。我想你可以用它们来引用任何东西,只是不确定这是他们的意图:"avoid using refs for anything that could be done declaratively". -
是的,refs 旨在创建一个可变对象,您可以随意改变它。我找到了这背后的原因,我现在会发布答案;在代码框里是 React.strictMode
-
并且只影响开发模式
-
是的,我怀疑是这样的:)我上周左右回答了一个类似的问题......
标签: javascript reactjs