1

親コンポーネントのループ内にある1つのサブ子コンポーネントがあります。サブ子コンポーネントの 1 つが親コンポーネントの状態を更新している場合、ループしているため、すべての子を再レンダリングしています。各反復の再レンダリングを回避するにはどうすればよいですか。その特定のサブ子を更新する必要があります。

import React, { useState } from "react";

function Parent() {
  const [selectedChild, setSelectedChild] = useState([]);

  const onChangeHandle = (event, id) => {
    const checked = event.target.checked;
    let updatedArray = [...selectedChild];
    if (checked) {
      if (!selectedChild.includes(id)) {
        updatedArray.push(id);
      }
    } else {
      var index = updatedArray.indexOf(id);
      if (index !== -1) {
        updatedArray.splice(index, 1);
      }
    }
    setSelectedChild(updatedArray);
  };

  return (
    <div>
      <table>
        <tbody>
          {[1, 2, 3].map((value, index) => {
            return (
              <Child
                key={index}
                index={index}
                value={value}
                handle={onChangeHandle}
                isSelected={selectedChild.includes(index)}
              />
            );
          })}
        </tbody>
      </table>
      <div>{selectedChild}</div>
    </div>
  );
}

function Child({ index, value, handle, isSelected }) {
  console.log("rendering child");

  return (
    <tr>
      <td>
        <SubChild
          isChecked={isSelected}
          onChangeHandle={handle}
          index={index}
        />
      </td>
      <td>
        hello {index} {value}
      </td>
    </tr>
  );
}

function SubChild({ isChecked, onChangeHandle, index }) {
  console.log("rendering subchild");

  return (
    <input
      type="checkbox"
      checked={isChecked}
      onChange={(event) => onChangeHandle(event, index)}
    />
  );
}

export default function App() {
  return (
    <div className="App">
      <Parent />
    </div>
  );
}

現在の動作: 上記のコードでは、子コンポーネントの 1 つでチェックボックス (サブ子) をクリックすると、親コンポーネントの状態 (selectedChild) が更新されます。したがって、ループが実行され、すべての子 (すべてのテーブル行) が再レンダリングされます。

予想される動作: その特定のサブ子のみを再レンダリングする必要があります (子を再レンダリングしてはいけません)

デモ: https://codesandbox.io/s/reactqa2-0c0md?file=/src/App.js

少し関連する質問:親コンポーネントの状態が更新されたときにループするすべての子コンポーネントを再レンダリングしないようにする方法

4

1 に答える 1

1

メモ化 ( useCallback/ React.memo) を使用し、機能の更新でハンドル ロジックを書き直す必要があります。

また、レンダリング後Childに新しいものがあるため、レンダリングを避けvalueます。

// Make a stable callback
const onChangeHandle = useCallback((event, id) => {
  setSelectedChild((updatedArray) => {
    if (event.target.checked) {
      if (!updatedArray.includes(id)) {
        return [...updatedArray, id];
      }
    } else {
      return updatedArray.filter((currId) => currId !== id);
    }
    return updatedArray;
  });
}, []);

// Memoize the component
const MemoChild = React.memo(Child);
const MemoSubChild = React.memo(SubChild);

reactQA2 の編集 (分岐)

于 2021-02-04T14:08:07.430 に答える