親コンポーネントの配列に対する子コンポーネントの更新によって引き起こされる無限の再レンダリングを防止します
P粉197639753
P粉197639753 2024-02-26 10:26:24
0
1
498

学生 (子) コンポーネント内

  • 変数の値が変更されると、useEffect フックは handleStudentsChange (親コンポーネントによって提供される関数) を介して親配列を更新します。

学生 (親) コンポーネント内

  • 現学生(児童)コンポーネントリスト
  • 無限ループを防ぐために、handleStudentsChange 関数は useCallback フック定義を使用します。しかし、うまくいかないようです。

質問/質問

  • 変更が発生すると、handleStudentsChange は無期限に実行されます
  • ###どうしてこれなの?そしてそれを修正する方法は?
  • 注: onSubmit ボタンは必要ありません
ここでコードを参照してください: 私はCodeSandBoxリンク

です

Student.tsx(子供) リーリー

Students.tsx(親) リーリー

上記のコードに示すように、student (子) コンポーネントで

React.memo を使用し、handleStudentsChangeuseCallback を使用してみました。できればできると思います。無限ループを防ぎます。ただし、無限ループは続きます。

P粉197639753
P粉197639753

全員に返信(1)
P粉955063662

###質問###

handleStudentsChange

は、変更が発生したときに一度だけ無限に実行されるのではなく、最初のレンダリングから無限に実行されます。これは、Student コンポーネントには handleStudentsChange を呼び出す useEffect があり、これにより Students コンポーネントの状態が更新され、 が発生するためです。 Studentコンポーネントが再レンダリングされ、useEffect が再度呼び出されます (無限ループ)。 ###解決### handleStudentsChange

を呼び出す必要があるのは、レンダリングのたびではなく、入力を更新した後でのみです。以下に、入力から

blur

イベント が発生した後に Students の状態を更新する例を示します。より賢い (そしてより複雑な) アプローチとして、props と state を比較して更新が必要かどうかを判断することもできますが、それは自分で判断してもらいます。

const {フラグメント、StrictMode、useCallback、useEffect、useState} = 反応;
const { createRoot } = ReactDOM;
const { TextField } = マテリアルUI;

関数 Student(小道具) {
  const [firstName, setFirstName] = useState(props.firstName);
  const [lastName, setLastName] = useState(props.lastName);
  const [グレード, setGrade] = useState(props.grade);
  const handleStudentsChange = props.handleStudentsChange;
  
  const onBlur = () => {
    handleStudentsChange(props.id, {
      ファーストネーム、
      苗字、
      学年、
    });
  };

  戻る (
    <フラグメント>
      <テキストフィールド
        ラベル="名"
        onBlur={onBlur}
        onChange={(イベント) => setFirstName(event.target.value)}
        値={名}
      />
      <テキストフィールド
        ラベル="姓"
        onBlur={onBlur}
        onChange={(イベント) => setLastName(event.target.value)}
        値={姓}
      />
      <テキストフィールド
        ラベル="グレード"
        onBlur={onBlur}
        onChange={(イベント) => setGrade(event.target.value)}
        値={グレード}
      />
    </フラグメント>
  );
}

関数 Student() {
  const [students, setStudents] = useState([
    { 名: "ジャスティン"、姓: "ビーバー"、学年: 100 },
    { 名: "ロバート"、姓: "オッペンハイマー"、学年: 100 }
  ]);

  const handleStudentsChange = useCallback(
    (インデックス、更新された学生) => {
      // console.log(index) // 値が変更されたときにのみ再レンダリングしたいのですが、無限ループになってしまいます
      
      console.log({ updatedStudent });

      setStudents((prevStudents) => {
        const updatedStudents = [...prevStudents];
        updatedStudents[インデックス] = updatedStudent;
        updatedStudents を返します。
      });
    }、
    []
  );

  戻る (
    <フラグメント>
      {students.map((student, インデックス) => {
        戻る (
          
        );
      })}
    </フラグメント>
  );
}

関数 App() {
  戻る (
    <div className="アプリ">
      
    </div>
  );
}

const root = createRoot(document.getElementById("root"));
root.render(<StrictMode><App /></StrictMode>);
<スクリプト クロスオリジン src="https://unpkg.com/react@18/umd/react.development.js"></script>
<scriptcrossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<scriptcrossorigin src="https://unpkg.com/@mui/material@latest/umd/material-ui.production.min.js"></script>
<div id="ルート"></div>

いいねを押す +0
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート