React报错之React Hook useEffect has a missing dependency
<p>正文从这开始~</p><h2 id="总览">总览</h2>
<p>当<code>useEffect</code>钩子使用了一个我们没有包含在其依赖数组中的变量或函数时,会产生"React Hook useEffect has a missing dependency"警告。为了解决该错误,禁用某一行的<code>eslint</code>规则,或者将变量移动到<code>useEffect</code>钩子内。</p>
<p><img src="https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/54acdba379ef4cb6854e4b1a4b4a0264~tplv-k3u1fbpfcp-watermark.image?"></p>
<p>这里有个示例用来展示警告是如何发生的。</p>
<pre><code>// App.js
import React, {useEffect, useState} from 'react';
export default function App() {
const = useState({country: '', city: ''});
// 👇️ objects/arrays are different on re-renders
const obj = {country: 'Chile', city: 'Santiago'};
useEffect(() => {
setAddress(obj);
console.log('useEffect called');
// ⛔️ React Hook useEffect has a missing dependency: 'obj'.
// Either include it or remove the dependency array. eslintreact-hooks/exhaustive-deps
}, []);
return (
<div>
<h1>Country: {address.country}</h1>
<h1>City: {address.city}</h1>
</div>
);
}
</code></pre>
<p>上述代码片段的问题在于,我们在<code>useEffect</code>钩子内部使用了<code>obj</code>变量,但我们没有在其依赖数组中包含该变量。</p>
<p>最明显的解决方法是将<code>obj</code>变量添加到<code>useEffect</code>钩子的依赖数组中。然而,在本例中,它将导致一个错误,因为在JavaScript中,对象和数组是通过引用进行比较的。</p>
<p><code>obj</code>变量是一个对象,在每次重新渲染时都有相同的键值对,但它每次都指向内存中的不同位置,所以它将无法通过相等检查并导致无限的重新渲染循环。</p>
<blockquote>
<p>在JavaScript中,数组也是通过引用进行比较。</p>
</blockquote>
<h2 id="禁用规则">禁用规则</h2>
<p>绕过"React Hook useEffect has a missing dependency"警告的一个方法是禁用某一行的<code>eslint</code>规则。</p>
<pre><code>import React, {useEffect, useState} from 'react';
export default function App() {
const = useState({country: '', city: ''});
const obj = {country: 'Chile', city: 'Santiago'};
useEffect(() => {
setAddress(obj);
console.log('useEffect called');
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div>
<h1>Country: {address.country}</h1>
<h1>City: {address.city}</h1>
</div>
);
}
</code></pre>
<p>依赖数组上方的注释禁用了单行的<code>react-hooks/exhausting-deps</code>规则。</p>
<blockquote>
<p>当<code>useEffect</code>钩子的第二个参数传递的是空数组时,只有当组件挂载或者卸载时才会调用。</p>
</blockquote>
<h2 id="依赖移入">依赖移入</h2>
<p>另一种解决办法是,将变量或者函数声明移动到<code>useEffect</code>钩子内部。</p>
<pre><code>import React, {useEffect, useState} from 'react';
export default function App() {
const = useState({country: '', city: ''});
useEffect(() => {
// 👇️ move object / array / function declaration
// inside of the useEffect hook
const obj = {country: 'Chile', city: 'Santiago'};
setAddress(obj);
console.log('useEffect called');
}, []);
return (
<div>
<h1>Country: {address.country}</h1>
<h1>City: {address.city}</h1>
</div>
);
}
</code></pre>
<p>我们把对象的变量声明移到了<code>useEffect</code>钩子里面。这就消除了警告,因为钩子不再依赖对象,对象声明在钩子内部。</p>
<h2 id="依赖移出">依赖移出</h2>
<p>另一个可能的解决方案是将函数或变量的声明移出你的组件,这可能很少使用,但最好知道。</p>
<pre><code>import React, {useEffect, useState} from 'react';
// 👇️ move function/variable declaration outside of component
const obj = {country: 'Chile', city: 'Santiago'};
export default function App() {
const = useState({country: '', city: ''});
useEffect(() => {
setAddress(obj);
console.log('useEffect called');
}, []);
return (
<div>
<h1>Country: {address.country}</h1>
<h1>City: {address.city}</h1>
</div>
);
}
</code></pre>
<p>这是很有用的,因为每次重新渲染App组件时,变量不会每次都重新创建。该变量在所有渲染中都会指向内存的相同位置,因此<code>useEffect</code>不需要在其依赖数组中跟踪它。</p>
<h2 id="usememo">useMemo</h2>
<p>另一个解决方案是使用<code>useMemo</code>钩子来得到一个记忆值。</p>
<pre><code>import React, {useMemo, useEffect, useState} from 'react';
export default function App() {
const = useState({country: '', city: ''});
// 👇️ get memoized value
const obj = useMemo(() => {
return {country: 'Chile', city: 'Santiago'};
}, []);
useEffect(() => {
setAddress(obj);
console.log('useEffect called');
// 👇️ safely include in dependencies array
}, );
return (
<div>
<h1>Country: {address.country}</h1>
<h1>City: {address.city}</h1>
</div>
);
}
</code></pre>
<p>我们使用<code>useMemo</code>钩子得到一个记忆值,该值在渲染期间不会改变。</p>
<blockquote>
<p><code>useMemo</code>钩子接收一个函数,该函数返回一个要被记忆的值和一个依赖数组作为参数。该钩子只有在其中一个依赖项发生变化时才会重新计算记忆值。</p>
</blockquote>
<h2 id="usecallback">useCallback</h2>
<p>请注意,如果你正在使用一个函数,你将使用<code>useCallback</code>钩子来获得一个在渲染期间不会改变的记忆回调。</p>
<pre><code>import React, {useMemo, useEffect, useState, useCallback} from 'react';
export default function App() {
const = useState({country: '', city: ''});
// 👇️ get memoized callback
const sum = useCallback((a, b) => {
return a + b;
}, []);
// 👇️ get memoized value
const obj = useMemo(() => {
return {country: 'Chile', city: 'Santiago'};
}, []);
useEffect(() => {
setAddress(obj);
console.log('useEffect called');
console.log(sum(100, 100));
// 👇️ safely include in dependencies array
}, );
return (
<div>
<h1>Country: {address.country}</h1>
<h1>City: {address.city}</h1>
</div>
);
}
</code></pre>
<p><code>useCallback</code>钩子接收一个内联回调函数和一个依赖数组,并返回一个记忆化版本的回调,该回调只在其中一个依赖发生变化时才会改变。</p>
<p>如果这些建议对你都不起作用,你总是可以用注释来消灭警告。</p>
<pre><code>import React, {useEffect, useState} from 'react';
export default function App() {
const = useState({country: '', city: ''});
const obj = {country: 'Chile', city: 'Santiago'};
useEffect(() => {
setAddress(obj);
console.log('useEffect called');
// 👇️ disable the rule for a single line
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
return (
<div>
<h1>Country: {address.country}</h1>
<h1>City: {address.city}</h1>
</div>
);
}
</code></pre><br><br>
来源:https://www.cnblogs.com/chuckQu/p/16608977.html
頁:
[1]