2023It 30天React練功坊-攻克常見實務/面試問題 Day6: Rendered more hooks than during the previous render.

tags: ItIron2023 react

前言

我們昨天看了一個簡單的條件渲染的範例,了解到為什麼你不該用布林值以外的值作為判斷條件渲染的標準,今天我們繼續來看有關渲染的問題吧!

本日題目

請觀察這個codesandbox

day6-demo-image
day6-demo-image-error

題目中的程式碼相當單純,我們希望在某些條件下才去執行我們的useEffect hook,比方説使用者有登入的話才去抓資料之類的。

export default function App() {
  const [condition, setCondition] = useState(false);

  if (condition) {
    useEffect(() => {
      // Do something
    }, []);
  }

  return (
    <div>
      <h1>
        Uncaught Error: Rendered more hooks than during the previous render.
      </h1>
      <button onClick={() => setCondition(!condition)}>Toggle Condition</button>
    </div>
  );
}

請試著解釋錯誤發生的原因並修復這個錯誤。

解答與基本解釋

這也是實務上相當常見的錯誤之一,最根本的原因在於react本身的機制,react依賴hooks的執行順序去確保每個state的值在多個useState & useEffect的使用下仍能保持正確,因此他必須每一次都執行與前一次渲染相同的hooks數量,同類型的錯誤也會發生在條件渲染上,若你在某個hook前就return整個組件,那麼相同的錯誤也會發生,這也是為什麼react官方總是要你把hooks放在最上方使用。

理解這一點之後我想解法就不言自明了,我們只要確保hooks的執行數量是相同的,因此你只要將上方的程式碼略作調整即可。

export default function App() {
  const [condition, setCondition] = useState(false);


  useEffect(() => { // 將條件放進hooks內即可
    if (condition) {
        // Do something
    }
  }, []);

  return (
    <div>
      <h1>
        Uncaught Error: Rendered more hooks than during the previous render.
      </h1>
      <button onClick={() => setCondition(!condition)}>Toggle Condition</button>
    </div>
  );
}

總結

今天的題目相當單純,不過確實是個在實務上必須注意的細節,正確得使用hook能讓你開發的稍微有效率一些(是的,我說稍微,react本身的缺點也不在少數),了解錯誤發生的原因會讓你更知道該如何修復同類型的bug! 各位明天見囉!

發表留言