繁体   English   中英

如何在不重新渲染未删除的项目的情况下从列表中删除项目?

[英]How can I delete an item from list without re-rendering undeleted Items?

感谢您的所有评论和有用的评论。 按照您的建议,请在下面找到代码沙箱链接

https://codesandbox.io/s/magical-butterfly-uk0fjq?file=/src/item.js

这可能会帮助您找出问题所在。 console中的一切都是显而易见的,有多个日志,考虑到示例的当前规模,这不会造成任何性能问题,但如果有很长的项目列表,可能会出现问题。

所以问题是,如何继续防止未删除的项目重新渲染,尽管父级( ItemList )重新渲染。

console显示Item渲染。

如前所述,我使用了useMemo + useCallback组合,但结果证明是不稳定的。

希望这个例子会有所帮助并且更加明确。

编辑

关于console log ,奇怪的是,沙盒示例记录了 2 次App 、2 次ItemList和 12 次Item ,而在计算机上它只记录 1-1-6 次

所以,如果你想最小化项目的重新渲染,你需要确保一些事情

记忆组件

你可以在你想要的组件上使用React.memo ,这将防止在 props/state 没有改变时重新渲染。

所以,使用

export default React.memo(Item);

代替

export default Item;

确保道具相同

当您渲染Item组件时,您将deleteItem作为 prop 传递,其值是从App组件接收的。 但是,这个函数不是一个稳定的(每次 App 组件渲染时都会重新定义它。并且由于App持有items状态,因此每次删除后都会重新渲染。这将触发一个新的deleteItem被定义,这将导致要重新渲染的Item

为了使这个稳定,你需要两件事。

  1. 使用React.useCallback ,当它的依赖关系保持不变时,它会重用相同的函数。
  2. 使用setItemsfunction形式

所以,而不是

const deleteItem = (newItem) => {
  const newItemList = items.filter(
    (item) => item.reference !== newItem.reference
  );
  setItems(newItemList);
};

利用

const deleteItem = React.useCallback((itemToDelete) => {
  setItems((currentItems) =>
    currentItems.filter((item) => item.reference !== itemToDelete.reference)
  );
}, []);

您的代码中也存在问题,您在其中.map数据但在返回每个Item之前将其推送到数组中并返回。 只需返回<Item ..>

所以而不是

    {props.data.map((item, index) => {
      const newList = [];
      newList.push(
        <Item
          deleteItem={props.deleteItem}
          key={item.reference}
          item={item}
        ></Item>
      );
      return newList;
    })}

    {props.data.map((item, index) => {
      return (
        <Item
          deleteItem={props.deleteItem}
          key={item.reference}
          item={item}
        ></Item>
      );
    })}

更新了所有更改的代码沙盒: https ://codesandbox.io/s/twilight-water-9iyobx

听起来您想遍历对象数组以在表中生成数据行,每行中的最后一个单元格是删除该行的“删除”按钮。 你可以做到这一点。 不需要useEffect

 const { useState } = React; // Pass in the data function Example({ data }) { // Set the state with the data const [ tableData, setTableData ] = useState(data); // When a remove button is clicked `filter` // out those rows that don't match the row id // and reset the state function handleRemove(e) { const { id } = e.target.closest('tr').dataset; const filtered = tableData.filter(obj => { return obj.name !== id; }); setTableData(filtered); } // Create some rows by mapping over the // table data return ( <table> {tableData.map(row => { return ( <Row key={row.name} row={row} handleRemove={handleRemove} /> ); })} </table> ); } // Create a table row and populate the cells // with the information from the row object function Row({ row, handleRemove }) { return ( <tr data-id={row.name}> <td>{row.name}</td> <td>{row.reference}</td> <td>{row.description}</td> <td> <button onClick={handleRemove} >Remove </button> </td> </tr> ); } const data = [ {name: "NAME 1", reference: "REF 1", description: "LOREM IPSUM"}, {name: "NAME 2", reference: "REF 2", description: "LOREM IPSUM"}, {name: "NAME 3", reference: "REF 3", description: "LOREM IPSUM"}, {name: "NAME 4", reference: "REF 4", description: "LOREM IPSUM"}, {name: "NAME 5", reference: "REF 5", description: "LOREM IPSUM"} ]; ReactDOM.render( <Example data={data} />, document.getElementById('react') );
 table { border-collapse: collapse; border: 1px solid #565656; } td { border: 1px solid #dfdfdf; padding: 0.5em;}
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script> <div id="react"></div>

更新状态时,您需要先传播先前的状态,然后再对其进行更新示例:

const deleteItem = (newItem) => {
  const newItemList = items.filter(item => item.reference !== newItem.reference);
  setItems(prev => (...prev, newItemList));
}

更新状态时,您需要先传播先前的状态,然后再更新它

并且取决于您的类型,您必须返回数组或对象 spreat 运算符打开先前的数组或对象,然后添加新数据 setItems(prev => [...prev, newItemList])

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM