我创建了这个非常简单的应用程序,希望可以解释这个问题。
我尝试使用记忆和回调,但是我相信它是重新渲染的,因为一旦我输入文本输入,playerArr总是在变化。
我的实际列表只有15个元素,但是重新渲染会导致输入时它变得非常慢。
有什么建议吗?我有一个截止日期,我感到压力很大=(是否会回到非挂钩状态?还是实施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>
);
});
编辑:我根据讨论内容编辑了应用。发生了同样的事情
答案 0 :(得分:1)
无论您做什么,您的<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
}
});