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>
  );
}

当前行为:在上面的代码中,当我单击其中一个子组件中的复选框(它是子子)时,它正在更新父组件状态(selectedChild)。所以循环正在执行,所有子项(所有表行)都在重新渲染。

预期行为:只有那个特定的子孩子必须重新渲染(即使它不应该重新渲染孩子)

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

小相关问题如何避免在父组件状态更新时重新渲染所有循环中的子组件

4

1 回答 1

1

You should use memoization (useCallback/React.memo) and rewrite handle logic with functional updates.

Also, you avoid Child to render, since you have a new value after rendering.

// 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);

Edit reactQA2 (forked)

于 2021-02-04T14:08:07.430 回答