簡體   English   中英

'React Hook useEffect has an missing dependency' 警告功能

[英]'React Hook useEffect has a missing dependency' warning with function

所以我有這個使用 useEffect() 鈎子的 React 組件:

const [stateItem, setStateItem] = useState(0);

useEffect(() => {
  if (condition) {
    myFunction();
  }
}, [stateItem]);

const myFunction = () => {
  return 'hello';
}

React 警告我“myFunction”是一個缺失的依賴項。 我(認為我)理解為什么並且我已經閱讀了許多要求或多或少相同的問題的類似問題,但答案始終是“將您的函數移動到 useEffect 鈎子中”。 如果不是從不同的地方調用 myFunction,這會很好,例如:

...
return (
  <Button onClick={() => myFunction()} />
);

因此我不能將我的函數放在 useEffect 鈎子中。

類似問題的一個答案是將函數放在組件之外,但這需要我將大量數據傳遞給我的函數,例如const myFunction(stateItem, setStateItem, someProp) => { stuff };

當有幾個函數有很多道具、狀態鈎子等要傳遞時,這會變得非常乏味。

除了在 useEffect 鈎子上方放置一個 linter ignore 注釋之外,還有什么更實用的方法可以解決這個問題嗎? 我發現這些東西使使用 React 鈎子非常不切實際。

我遇到了這個問題。

React 總是試圖讓你的效果保持最新。 如果您不傳遞依賴項數組,React 將在每次渲染后運行該效果,以防萬一。

這將在每個渲染上運行

useEffect(()=> {
  // DO SOMETHING
});

如果你傳遞一個空數組,你基本上是在告訴你你的效果不依賴於任何東西,並且只運行一次是安全的。

這只會運行一次

useEffect(()=> {
  // DO SOMETHING
},[]);

如果您填充依賴項數組,則表示您的效果取決於那些特定的事物,如果其中任何一個發生變化,則效果需要再次運行,否則就不必了。

這只會在somePropsomeFunction更改時運行。

useEffect(()=> {
  // DO SOMETHING
},[someProp,someFuction]);

注意:記住函數、對象和數組是通過引用比較的

所以,基本上你的選擇是:

  • 將函數移動到效果的主體。
  • 添加它做依賴數組

如果選擇將其添加到數組中,則需要決定以下事項:

如果該功能被修改,您是否需要再次運行效果?

如果這是真的,只需將它添加到依賴項數組,React 將負責在每次函數更改時重新運行您的效果。

如果這不是真的,請將您的函數包裝到useCallback以便您可以在渲染中保持其引用相同。 您還可以向useCallback添加依賴項數組以控制何時需要重新創建函數。

EXTRA函數需要重新創建,但您不想重新運行。

  • 使用useRef()添加一些變量以跟蹤效果是否運行過一次,並在您的效果中寫入檢查以停止效果,如果它之前運行過。 喜歡:
const effectHasRun_ref = useRef(false);
useEffect(()=>{
  if (effectHasRun_ref.current === true) {
    return;
  }
  else {
    // RUN YOUR EFFECT
    effectHasRun_ref.current = true;
  }
},[yourFunction]);

因此,您的目標似乎是將您的功能保留在您的組件中,並且

  1. 您不想將它移動到useEffect因為您想在其他地方使用它
  2. 你不想把它移到你的函數之外,因為你想避免從組件傳遞參數

在這種情況下,我認為最好的解決方案是使用useCallback鈎子,如下所示


function YourComponent(props){

  const [stateItem, setStateItem] = useState(0);

  //wrap your logic in useCallback hook
  const myFunction = React.useCallback(
    () => {

      //if you use any dependencies in this function add them to the deps array of useCallback
      //so if any of the dependencies change thats only when the function changes

      return 'hello'
    }, [deps])

    useEffect(() => { 
       if(condition) {
          myFunction();
       }

    //add your function to the dependency array as well
    //the useCallback hook will ensure your function is always constant on every rerender thus you wont have any issues by putting it in the deps array, besides the #1 rule is NEVER LIE ABOUT YOUR DEPENDENCIES
    //the function only changes if the dependencies to useCallback hook change!!
    }, [stateItem, myFunction ])

   return (
     <Button onClick={() => myFunction()} />
   );
}


useCallback鈎子將確保您的函數在每次重新渲染時始終保持不變,因此將它放在 deps 數組中不會有任何問題。 該函數僅在 useCallback 鈎子的依賴項更改時才會更改。 通過這樣做,我們保持了鈎子的黃金法則,永遠不要對你的依賴撒謊 希望有幫助。 您可能想閱讀Dan Abramov 撰寫的這篇博客文章

我建議你根本不要使用 useEffect ,據我所知,你想在更新某個狀態時調用某個函數。 為此,我建議您寧願編寫一個自定義函數,該函數將在更新時調用(例如輸入)。

現在你可以調用這個函數並更新你的狀態,因為你知道這個函數只會在只有這個特定狀態即將更新時才會被調用,然后你可以調用你的另一個函數。

如果你有類似 changeHandler 的東西,你也可以在那里做,但我寧願建議寫一個自定義函數。

小示例代碼:

const [stateItem, setStateItem] = useState(0);

const myFunction = () => {
   // do something
};

const myOtherFunc = (value) => {
   setStateItem(value);

   if (condition) {
      myFunction();
   }
};

我希望我正確理解了您的問題,這很有幫助。

您可以使用useRef()代替onClick來調用該函數,盡管該函數主要用於訪問DOM,但它可以工作。

const [stateItem, setStateItem] = useState(0);

const onClickRef = React.useRef();

useEffect(() => {

  const myFunction = () => {
    return 'hello';
  }

  if (condition) {
   onClickRef.current.addEventListener('click', myFunction);
  }

}, [stateItem]);

return (
  <Button ref={onClickRef} />
);

TLDR :將 myFunction 添加到依賴項數組,如下所示

React useEffect 有一個叫做依賴數組的東西,它的作用基本上可以幫助你並知道何時重新運行效果。 基本上你應該把所有定義的東西都放在效果之外。

在此效果中,您將 stateItem 作為此效果的依賴項,這意味着每次更改時,react 都會重新運行此效果。 現在,您可能已經猜到您正在使用myFunction ,它在效果之外也有很好的定義,這意味着 react 應該知道它何時更新,以便它知道。 要修復此警告,只需像這樣將函數在依賴項數組中包含一個項即可。

const [stateItem, setStateItem] = useState(0);

useEffect(() => {
  if (condition) {
    myFunction();
  }
}, [stateItem, myFunction]);

const myFunction = () => {
  return 'hello';
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM