如何仅渲染子子项而不渲染所有高级组件

时间:2021-02-04 13:12:25

标签: javascript reactjs performance react-hooks react-memo

我有一个位于父组件循环内的子子组件。当子子组件之一正在更新父组件的状态时,它正在重新渲染所有子组件,因为它是循环的。如何避免每次迭代重新渲染。它应该更新那个特定的子孩子。

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

小相关问题How to avoid rerender all child components which in loop when parent component state update

1 个答案:

答案 0 :(得分: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);

Edit reactQA2 (forked)