如何仅渲染子子项而不渲染所有高级组件 [英] How to render only subchild without rendering all high level component

查看:61
本文介绍了如何仅渲染子子项而不渲染所有高级组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

import React, { useState } from "react";函数父(){const [selectedChild, setSelectedChild] = useState([]);const onChangeHandle = (event, id) =>{const 检查 = event.target.checked;让 updatedArray = [...selectedChild];如果(检查){如果 (!selectedChild.includes(id)) {updatedArray.push(id);}} 别的 {var index = updatedArray.indexOf(id);如果(索引!== -1){updatedArray.splice(index, 1);}}setSelectedChild(updatedArray);};返回 (<div><表格>{[1, 2, 3].map((value, index) => {返回 (<孩子键={索引}索引={索引}价值={价值}句柄={onChangeHandle}isSelected={selectedChild.includes(index)}/>);})}</tbody><div>{selectedChild}</div>

);}function Child({ index, value, handle, isSelected }) {console.log(渲染子节点");返回 (<tr><td><子孩子isChecked={isSelected}onChangeHandle={句柄}索引={索引}/></td><td>你好 {index} {value}</td></tr>);}function SubChild({ isChecked, onChangeHandle, index }) {console.log(渲染子子级");返回 (<输入类型=复选框"已检查={isChecked}onChange={(事件)=>onChangeHandle(事件,索引)}/>);}导出默认函数 App() {返回 (

<父/>

);}

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

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

演示:

I m having one sub child component which is inside a loop of parent component. when one of the sub child components is updating the state of parent component, it is re-rendering the all children since it is loop. How can i avoid the re-render for each iteration. It should update that particular sub child.

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

Current behaviour: In above code, When i m clicking on the checkbox(which is Sub child) in one of the children component, it is updating the parent component state(selectedChild). So the loop is executing and all children(all table rows) are re rendering.

Expected behaviour: Only that particular sub child have to go for re-render (even it should not re-render child)

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

Little related question: How to avoid rerender all child components which in loop when parent component state update

解决方案

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

这篇关于如何仅渲染子子项而不渲染所有高级组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆