状态设置器的react-hooks/exhaustive-deps警告有什么意义?
P粉465287592
2023-09-01 22:11:31
<p>我正在使用 React 构建分页。</p>
<p>该应用程序使用状态管理分页和搜索。我想在搜索词更改时将分页重置为第 1 页。</p>
<pre class="brush:php;toolbar:false;">// Simplified example
function useSearchTerm() {
return React.useState("");
}
function usePage() {
return React.useState(1);
}
function MyComponent(){
const [searchTerm, setSearchTerm] = useSearchTerm()
const [page, setPage] = usePage();
useEffect(() => {
setPage(1);
}, [searchTerm]); // <-- Here is the ESLint warning
}</pre>
<p>这给我带来了 ESLint 警告 <code>React Hook useEffect 缺少依赖项:“setPage”。要么包含它,要么删除 useEffect 挂钩上的依赖项 array.eslintreact-hooks/exhaustive-deps。</p>
<p>但是,当然,如果我在依赖项中包含 setPage,则每次渲染时都会调用该效果。</p>
<p>我在这个用例上做错了什么吗?</p>
这个中间函数似乎是问题所在:
由
useState
返回的状态设置函数本身不会在每次渲染时重新创建,但通过此外部函数调用它似乎会破坏这一点。这导致依赖项发生变化,如useEffect
依赖项数组所观察到的。如果您不需要这个
usePage
函数(在示例中您不需要,但在更大的上下文中可能存在有意义的情况),那么只需将其完全删除并使用直接useState
:通常,人们无论如何都不想在函数内调用钩子,因为它可以快速且轻松地导致违反必须在每次渲染上一致且以相同顺序调用钩子的规则。因此,最好将钩子调用保留在组件本身的主体中(以及组件逻辑的早期)。
有时,在某些情况下,您确实希望自定义函数充当
useEffect
中的依赖项。由于声明的函数在每次渲染时都会重新声明,因此您会遇到上面遇到的问题。为了解决这个问题,您可以将该函数包装在useCallback
挂钩中,该挂钩本身也有一个依赖项数组,与useEffect
非常相似。这个钩子的目的是创建自定义函数,React 可以将这些函数跨渲染缓存为单个函数实例(除非依赖项发生变化)。例如: