【发布时间】:2022-10-31 16:58:43
【问题描述】:
我只是想知道如果我们将第二个参数作为null 或undefined 来代替依赖项数组,useEffect 将如何表现。它会在每个周期渲染吗?还是只有一次?任何线索将不胜感激。
【问题讨论】:
标签: javascript reactjs react-hooks frontend
我只是想知道如果我们将第二个参数作为null 或undefined 来代替依赖项数组,useEffect 将如何表现。它会在每个周期渲染吗?还是只有一次?任何线索将不胜感激。
【问题讨论】:
标签: javascript reactjs react-hooks frontend
如果您创建一个没有第二个参数的useEffect,或者一个等于undefined 或null,则回调将在每次渲染时执行。如果您已明确键入 undefined 或 null 作为第二个参数,并且您的编辑器中有 Eslint,您将收到以下警告:
React Hook useEffect was passed a dependency list that is not an array literal. This means we can't statically verify whether you've passed the correct dependencies. (react-hooks/exhaustive-deps)
在像下面这样的情况下,如果您没有在回调中改变 state,这对您的应用程序没有任何伤害,它只会在每次渲染时记录“Hello Word”。
export default function App() {
const [state, setState]= useState(true);
useEffect(() => {
console.log("Hello Word");
});
return (
<div>
<button onClick = {()=>setState(!state)}>Toggle State</button>
</div>
);
}
在以下情况下,当您在回调中更改 state 时,它将导致渲染的无限循环。这是因为状态更改会触发渲染,并且在每次渲染时都会执行回调。
export default function App() {
const [state, setState]= useState(true);
useEffect(() => {
setState(!state);
});
return (
<div>
<button onClick = {()=>setState(!state)}>Toggle State</button>
</div>
);
}
为了涵盖所有用例,有一个使用空依赖数组作为第二个参数的用例,其中回调仅在第一次渲染时执行:
export default function App() {
const [state, setState]= useState(true);
useEffect(() => {
setState(!state);
},[]);
return (
<div>
<button onClick = {()=>setState(!state)}>Toggle State</button>
</div>
);
}
最后,在第一次渲染时调用回调的那个,并且每次依赖数组中的一些 state 发生变化时:
export default function App() {
const [state, setState]= useState(true);
useEffect(() => {
console.log("Hello Word");
// setState(!state); if you mutate state here, it will cause an infinite loop of renders
},[state]);
return (
<div>
<button onClick = {()=>setState(!state)}>Toggle State</button>
</div>
);
}
【讨论】:
如果 deps 未定义或为空,它将重新渲染每个圆圈。
在 react 源中,当第二个参数未定义时,deps 将为null,updateEffectImpl,将始终执行 pushEffect,并渲染每个圆圈:
function updateEffectImpl(fiberFlags, hookFlags, create, deps): void {
const nextDeps = deps === undefined ? null : deps;
if (currentHook !== null) {
// .eg
}
// always execute
hook.memoizedState = pushEffect(
HookHasEffect | hookFlags,
create,
destroy,
nextDeps,
);
}
【讨论】: