ReactJS如何在循环中记忆以呈现相同的组件

ReactJS如何在循环中记忆以呈现相同的组件,reactjs,react-hooks,memoization,Reactjs,React Hooks,Memoization,我有一个使用循环创建多个组件的组件,但我只需要重新渲染正在修改的实例,而不需要重新渲染其余的实例。这是我的方法: function renderName(item) { return ( <TextField value={item.value || ''} onChange={edit(item.id)} /> ); } function renderAllNames(items) {

我有一个使用循环创建多个组件的组件,但我只需要重新渲染正在修改的实例,而不需要重新渲染其余的实例。这是我的方法:

    function renderName(item) {
       return (
          <TextField value={item.value || ''} onChange={edit(item.id)} />
       );
    }
    
    function renderAllNames(items) {
       const renderedItems = [];
       items.forEach(x => {
          const item = React.useMemo(() => renderName(x), [x]);
          renderedItems.push(item);
       });
       return renderedItems;
    };
    
    return (
      <>
         {'Items'}
         {renderAllNames(names)};
      </>
    );
也不管用。。。基本方法很有效

function renderAllNames(items) {
           const renderedItems = [];
           items.forEach(x => {
              renderedItems.push(renderName(x));
           });
           return renderedItems;
        };
但是每次我编辑任何字段时,它都会呈现所有的动态组件,那么我如何才能将其记录下来,以便只重新呈现正在编辑的项目呢?

您正在破坏该选项。钩子只能在组件的顶层使用,这样React才能保证调用顺序。组件备忘录实际上也只能使用React.memo来完成,组件只能在全局范围内声明,而不能在其他组件内声明

我们可以将
renderName
转换为它自己的组件,
renderName

function RenderName({item, edit}) {
    return (
      <TextField value={item.value || ''} onChange={() => edit(item.id)} />
   );
}
React.memo
默认情况下对所有道具进行严格比较。由于
是一个对象,并且没有两个对象严格相等,因此必须对属性进行深入比较。旁注:只有当
edit
是一个引用稳定的函数时,这才起作用。您尚未显示它,但它必须包装在自己的记忆挂钩中,例如
useCallback
,或者完全脱离渲染周期

现在回到父组件中,您可以直接映射
名称

return (
  <>
     {'Items'}
     {names.map(name => <MemoRenderName item={name} edit={edit}/>)}
  </>
);
返回(
{'Items'}
{names.map(name=>)}
);

您能提供组件的完整代码吗?嘿,我想在这里添加注释,请原谅:)编辑道具是匿名函数,可能无法通过您的平等性检查。所以,您应该使用useCallback记住这一点,或者通过命名thje函数或将其设置为变量来说明这一点。在备忘录的自定义相等函数中,可以从Lodash传递一个简单的等相等函数。也可以提高可读性,在我的op.@CaioKoiti中,我的回答假设
edit
是OPs post中的命名函数。没有理由认为它是匿名的,我在回答中确实说过关于
useCallback
。我不同意在这里使用深度平等检查器。在试图提高性能时,应该小心使用更昂贵的算法。更好的办法是将对象中的所有值分解为它们自己的道具,这样就根本不需要自定义检查。我在这里没有这样做,因为这篇文章的目的是阐明
response.memo
是如何工作的。
const MemoRenderName = React.memo(RenderName, (prev, next) => {
  const idEqual = prev.item.id === next.item.id;
  const valEqual = prev.item.value === next.item.value;
  const editEqual = prev.edit === next.edit;

  return idEqual && valEqual && editEqual;
});
return (
  <>
     {'Items'}
     {names.map(name => <MemoRenderName item={name} edit={edit}/>)}
  </>
);