簡體   English   中英

使用默認參數和 useEffect 防止函數組件無限循環

[英]Prevent infinite loop on function component with default parameter and useEffect

在 React 中創建函數組件並設置默認參數時,一切都按預期工作,並且組件將被渲染一次。 但是一旦你添加了一個像useEffect這樣的useEffect並在依賴數組中使用這個參數,組件就會永遠重新渲染。 我在這里創建了一個簡單的演示: https : //codesandbox.io/s/infinite-useeffect-loop-on-default-value-tv7hj?file=/ src/ TestComponent.jsx

原因很明顯,因為當使用一個對象作為默認參數時,它會被再次創建並且不會等於前一個。 當然,這不會發生在原始默認參數值(如數字或字符串)上。

除了使用defaultProps之外,還有什么更好的方法可以避免這種副作用?

是的,而不是默認值設定value來作為一個對象,只需將其設置為false。 然后檢查value是否為真,如果是,則訪問正確的屬性,否則,僅顯示默認值。 新代碼

它會是這樣的:

import { useEffect, useState } from "react";

const TestComponent = ({ value = false }) => {
  const [calcValue, setCalcValue] = useState(0);

  useEffect(() => {
    setCalcValue((cur) => cur + 1);
  }, [value]);

  return (
    <div>
      {value ? value.name : "Test"}:{calcValue}
    </div>
  );
};

你得到無限循環的原因是因為value的引用不斷變化。

第一次渲染組件時,它看到一個對 value 的新引用,這會觸發useEffect ,它反過來修改組件的狀態,這導致新的渲染,這會導致再次重新創建value ,因為對該變量的舊引用已更改。

解決這個問題的最簡單方法是在組件外部創建一個默認值並使用它(defaultProps解決方案基本相同):

import { useEffect, useState } from "react";

const defaultValue = {name: "Test"}; // <-- default here
const TestComponent = ({ value = defaultValue }) => {
  const [calcValue, setCalcValue] = useState(0);

  useEffect(() => {
    setCalcValue((cur) => cur + 1);
  }, [value]);

  return (
    <div>
      {value.name}:{calcValue}
    </div>
  );
};

這樣做將確保每次渲染組件時,它都會看到對value的相同引用,因此useEffect鈎子只運行一次。


解決這個問題的另一種方法是首先用memo包裝你的組件,然后創建一個采用原始value的新狀態變量,並使你的useEffect鈎子依賴於這個新狀態變量:

const TestComponent = React.memo(({ value = {name: "Test"} }) => {
  const [calcValue, setCalcValue] = useState(0);
  const [myValue, setMyValue] = useState(value);

  useEffect(() => {
    setCalcValue((cur) => cur + 1);
  }, [myValue]);

  return (
    <div>
      {myValue.name}:{calcValue}
    </div>
  );
});

我們用memo包裝組件的原因是,如果prop 的(而不是reference )發生了變化,它只會在狀態更改后重新渲染。 您可以通過提供自定義比較函數作為第二個參數來更改memo檢測道具更改的方式。

暫無
暫無

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

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