解決React報錯React Hook useEffect has a missing dependency

總覽

useEffect鉤子使用瞭一個我們沒有包含在其依賴數組中的變量或函數時,會產生"React Hook useEffect has a missing dependency"警告。為瞭解決該錯誤,禁用某一行的eslint規則,或者將變量移動到useEffect鉤子內。

這裡有個示例用來展示警告是如何發生的。

// App.js
import React, {useEffect, useState} from 'react';
export default function App() {
  const [address, setAddress] = 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>
  );
}

上述代碼片段的問題在於,我們在useEffect鉤子內部使用瞭obj變量,但我們沒有在其依賴數組中包含該變量。

最明顯的解決方法是將obj變量添加到useEffect鉤子的依賴數組中。然而,在本例中,它將導致一個錯誤,因為在JavaScript中,對象和數組是通過引用進行比較的。

obj變量是一個對象,在每次重新渲染時都有相同的鍵值對,但它每次都指向內存中的不同位置,所以它將無法通過相等檢查並導致無限的重新渲染循環。

在JavaScript中,數組也是通過引用進行比較。

禁用規則

繞過"React Hook useEffect has a missing dependency"警告的一個方法是禁用某一行的eslint規則。

import React, {useEffect, useState} from 'react';
export default function App() {
  const [address, setAddress] = 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>
  );
}

依賴數組上方的註釋禁用瞭單行的react-hooks/exhausting-deps規則。

useEffect鉤子的第二個參數傳遞的是空數組時,隻有當組件掛載或者卸載時才會調用。

依賴移入

另一種解決辦法是,將變量或者函數聲明移動到useEffect鉤子內部。

import React, {useEffect, useState} from 'react';
export default function App() {
  const [address, setAddress] = 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>
  );
}

我們把對象的變量聲明移到瞭useEffect鉤子裡面。這就消除瞭警告,因為鉤子不再依賴對象,對象聲明在鉤子內部。

依賴移出

另一個可能的解決方案是將函數或變量的聲明移出你的組件,這可能很少使用,但最好知道。

import React, {useEffect, useState} from 'react';
// 👇️ move function/variable declaration outside of component
const obj = {country: 'Chile', city: 'Santiago'};
export default function App() {
  const [address, setAddress] = useState({country: '', city: ''});
  useEffect(() => {
    setAddress(obj);
    console.log('useEffect called');
  }, []);
  return (
    <div>
      <h1>Country: {address.country}</h1>
      <h1>City: {address.city}</h1>
    </div>
  );
}

這是很有用的,因為每次重新渲染App組件時,變量不會每次都重新創建。該變量在所有渲染中都會指向內存的相同位置,因此useEffect不需要在其依賴數組中跟蹤它。

useMemo

另一個解決方案是使用useMemo鉤子來得到一個記憶值。

import React, {useMemo, useEffect, useState} from 'react';
export default function App() {
  const [address, setAddress] = 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
  }, [obj]);
  return (
    <div>
      <h1>Country: {address.country}</h1>
      <h1>City: {address.city}</h1>
    </div>
  );
}

我們使用useMemo鉤子得到一個記憶值,該值在渲染期間不會改變。

useMemo鉤子接收一個函數,該函數返回一個要被記憶的值和一個依賴數組作為參數。該鉤子隻有在其中一個依賴項發生變化時才會重新計算記憶值。

useCallback

請註意,如果你正在使用一個函數,你將使用useCallback鉤子來獲得一個在渲染期間不會改變的記憶回調。

import React, {useMemo, useEffect, useState, useCallback} from 'react';
export default function App() {
  const [address, setAddress] = 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
  }, [obj, sum]);
  return (
    <div>
      <h1>Country: {address.country}</h1>
      <h1>City: {address.city}</h1>
    </div>
  );
}

useCallback鉤子接收一個內聯回調函數和一個依賴數組,並返回一個記憶化版本的回調,該回調隻在其中一個依賴發生變化時才會改變。

如果這些建議對你都不起作用,你總是可以用註釋來消滅警告。

import React, {useEffect, useState} from 'react';
export default function App() {
  const [address, setAddress] = 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>
  );
}

原文鏈接:bobbyhadz.com/blog/react-…

以上就是解決React報錯React Hook useEffect has a missing dependency的詳細內容,更多關於React 報錯解決的資料請關註WalkonNet其它相關文章!

推薦閱讀: