javascript - 在编辑列表中的元素时如何防止整个列表重新呈现?

标签 javascript reactjs

我创建了这个非常简单的应用程序,希望能够解释这个问题。

我尝试使用内存和回调,但我相信它正在重新渲染,因为一旦我输入文本输入,playerArr 总是在变化。

我的实际列表只有 15 个元素,但重新渲染导致它在输入时变得非常慢。

有什么建议吗?我有一个截止日期,我感到压力很大 =( 回到非 Hook 有帮助吗?还是实现 redux?不确定性能因素。

function App() {
  const [player1, setPlayer1] = React.useState({
    firstName: "First",
    lastName: "Last ",
    id: uuidv4()
  });

  const [player2, setPlayer2] = React.useState({
    firstName: "First",
    lastName: "Last",
    id: uuidv4()
  });

  const [player3, setPlayer3] = React.useState({
    firstName: "First",
    lastName: "Last",
    id: uuidv4()
  });

  return (
    <div>
      <State
        player1={player1}
        player2={player2}
        player3={player3}
        setPlayer1={setPlayer1}
        setPlayer2={setPlayer2}
        setPlayer3={setPlayer3}
      />
    </div>
  );
}

//----------------------------------------------------------

export const State = React.memo(({player1, player2, player3, setPlayer1, setPlayer2, setPlayer3}) => {
  const playerArr = [player1, player2, player3];
  const setPlayerArr = [setPlayer1, setPlayer2, setPlayer3];

  return (
    <div>
      <Playlist
        playerArr={playerArr}
        setPlayerArr={setPlayerArr}
      />
    </div>
  );
});

//----------------------------------------------------------

export const Playlist = React.memo(({playerArr, setPlayerArr}) => {
  return (
    <div>
      {
        playerArr.map((player, index) => (
          <Player
            key={player.id}
            player={player}
            setPlayer={setPlayerArr[index]}
          />
        ))
      }
    </div>
  );
});

//----------------------------------------------------------

export const Player = React.memo(({player, setPlayer}) => {
  const handleOnChange = React.useCallback((event) => {
    const playerCopy = {...player};
    playerCopy[event.target.name] = event.target.value;
    setPlayer(playerCopy);
  }, [player, setPlayer]);

  return (
    <div>
      <input type={"text"} name={"firstName"} value={player.firstName} onChange={handleOnChange}/>
      <input type={"text"} name={"lastName"} value={player.lastName} onChange={handleOnChange}/>
    </div>
  );
});

编辑:我根据讨论编辑了应用程序。同样的事情发生

最佳答案

无论你做什么,你的<App><Playlist>每次有用户输入时,组件(即使它们被内存)都必须重新呈现,因为这是您存储状态的地方,这是可以预料的。

你能做的最好的事情就是记住每个 <Player>组件,以便当列表重新呈现时,每个单独的列表项不一定重新呈现自身。为此,您可以将“areEqual”函数作为第二个参数传递给React.memo。 .请参阅 React 文档中的示例:https://reactjs.org/docs/react-api.html#reactmemo

在您的情况下,它可能看起来像这样:

export const Player = React.memo(({player, setPlayer}) => {
  const handleOnChange = React.useCallback((event) => {
    const playerCopy = {...player};
    playerCopy[event.target.name] = event.target.value;
    setPlayer(playerCopy);
  }, [player, setPlayer]);

  return (
    <div>
      <input type={"text"} name={"firstName"} value={player.firstName} onChange={handleOnChange}/>
      <input type={"text"} name={"lastName"} value={player.lastName} onChange={handleOnChange}/>
    </div>
  );
}, (prevProps, nextProps) => {
  // Check to see if the data is the same
  if (prevProps.firstName === nextProps.firstName
    && prevProps.lastName === nextProps.lastName
    && prevProps.id === nextProps.id) {
    return true; // Return true if they ARE the same
  } else {
    return false; // Return false if they are NOT the same
  }
});

有时,如果您要比较的数据是字符串和/或数字的简单集合,您可以使用 JSON.stringify作为将其转换为字符串并比较字符串的简写方式:

export const Player = React.memo(({player, setPlayer}) => {
  const handleOnChange = React.useCallback((event) => {
    const playerCopy = {...player};
    playerCopy[event.target.name] = event.target.value;
    setPlayer(playerCopy);
  }, [player, setPlayer]);

  return (
    <div>
      <input type={"text"} name={"firstName"} value={player.firstName} onChange={handleOnChange}/>
      <input type={"text"} name={"lastName"} value={player.lastName} onChange={handleOnChange}/>
    </div>
  );
}, (prevProps, nextProps) => {
  // Check to see if the data is the same
  if (JSON.stringify(prevProps) === JSON.stringify(nextProps)) {
    return true; // Return true if they ARE the same
  } else {
    return false; // Return false if they are NOT the same
  }
});

关于javascript - 在编辑列表中的元素时如何防止整个列表重新呈现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56940510/

相关文章:

javascript - 如何在 javascript 中添加第三个淡入效果?

javascript - Uncaught TypeError : hook. apply 不是在 react-router 中使用 onEnter 的函数

javascript - 由于无效的钩子(Hook)调用错误,比较自定义的 props 不起作用

javascript - Angular : Update model from directive

node.js - 当 MongoDB 中存在数据时 API 返回空数组

javascript - 如何使用 FileUpload 向受 Azure AD 保护的 REST API 发出 REST API 发布请求

reactjs - 获取 : Could not detect any platform in the source directory. 以在 Azure 静态站点上部署 React

javascript - 打印任何 javascript 对象

仅限 Javascript - 对一堆 DIV 进行排序

javascript - 我如何在给定代码中使用 AJAX 来加载图像