我创建了这个非常简单的应用程序,希望能够解释这个问题。
我尝试使用内存和回调,但我相信它正在重新渲染,因为一旦我输入文本输入,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/