如何使用 useMemo 钩子来记忆 children
How to use useMemo hook to memoize children
我有一个组件可以在传单地图上呈现标记。每次服务器为一个或多个标记发送新位置时,标记都需要更改位置。
如何在没有 re-render 所有标记的情况下更改已更改其位置的特定标记的位置?
我想使用 useMemo 钩子,但我没有成功在地图函数上使用这个钩子,因为无法在回调中调用钩子。
const Participants = () => {
// This pattern is showed here: https://medium.com/digio-australia/using-the-react-usecontext-hook-9f55461c4eae
const { participants, setParticipants } = useContext(ParticipantsContext);
useEffect(() => {
const socket = io('http://127.0.0.1:8000');
socket.on('location', data => {
if (data) {
const ps = [...participants];
// currently change the position of the first participant
ps[0].lat = data.dLat;
ps[0].long = data.dLong;
setParticipants(ps);
console.log(data);
}
});
}, []);
const renderParticipants = () => {
return participants.map(p => {
return (
<ParticipantIcon key={p.id} id={p.id} position={[p.lat, p.long]}>
{p.id}
</ParticipantIcon>
);
});
};
return <div>{renderParticipants()}</div>;
};
const ParticipantIcon = ({ id, position, children }) => {
// This is showing if the component rerenderd
useEffect(() => {
console.log(id);
});
return (
<MapIcon icon={droneIcon} position={position}>
{children}
</MapIcon>
);
};
实际结果是,每次套接字收到位置时,它都会 re-render 所有参与者的图标,而不是 re-render 数组中的第一个参与者。
因为您在每次渲染时更新整个 position
数组,所以对表示先前位置和当前位置的数组的引用将不同,尽管纬度和经度可能完全相同。要使其工作,请将 PariticpantIcon
包装在 React.memo
内,然后执行以下任一操作:
将position
拆分为2个不同的道具,即lat
和long
。然后在 ParticipantIcon
里面你可以把它们放回去。 This codesandbox 解释得最好。
重构participants
数组。最初将 lat
和 long
组合在一起会阻止在渲染阶段创建新引用。 This codesandbox 对此进行了演示。
好处: 因为 ParticipantIcon
组件只显示 id,你不妨像这样让它更干净:
const ParticipantIcon = ({ id, position, children }) => {
// This is showing if the component rerenderd
useEffect(() => {
console.log(id);
});
return (
<MapIcon icon={droneIcon} position={position}>
{id}
</MapIcon>
);
};
我有一个组件可以在传单地图上呈现标记。每次服务器为一个或多个标记发送新位置时,标记都需要更改位置。 如何在没有 re-render 所有标记的情况下更改已更改其位置的特定标记的位置?
我想使用 useMemo 钩子,但我没有成功在地图函数上使用这个钩子,因为无法在回调中调用钩子。
const Participants = () => {
// This pattern is showed here: https://medium.com/digio-australia/using-the-react-usecontext-hook-9f55461c4eae
const { participants, setParticipants } = useContext(ParticipantsContext);
useEffect(() => {
const socket = io('http://127.0.0.1:8000');
socket.on('location', data => {
if (data) {
const ps = [...participants];
// currently change the position of the first participant
ps[0].lat = data.dLat;
ps[0].long = data.dLong;
setParticipants(ps);
console.log(data);
}
});
}, []);
const renderParticipants = () => {
return participants.map(p => {
return (
<ParticipantIcon key={p.id} id={p.id} position={[p.lat, p.long]}>
{p.id}
</ParticipantIcon>
);
});
};
return <div>{renderParticipants()}</div>;
};
const ParticipantIcon = ({ id, position, children }) => {
// This is showing if the component rerenderd
useEffect(() => {
console.log(id);
});
return (
<MapIcon icon={droneIcon} position={position}>
{children}
</MapIcon>
);
};
实际结果是,每次套接字收到位置时,它都会 re-render 所有参与者的图标,而不是 re-render 数组中的第一个参与者。
因为您在每次渲染时更新整个 position
数组,所以对表示先前位置和当前位置的数组的引用将不同,尽管纬度和经度可能完全相同。要使其工作,请将 PariticpantIcon
包装在 React.memo
内,然后执行以下任一操作:
将
position
拆分为2个不同的道具,即lat
和long
。然后在ParticipantIcon
里面你可以把它们放回去。 This codesandbox 解释得最好。重构
participants
数组。最初将lat
和long
组合在一起会阻止在渲染阶段创建新引用。 This codesandbox 对此进行了演示。
好处: 因为 ParticipantIcon
组件只显示 id,你不妨像这样让它更干净:
const ParticipantIcon = ({ id, position, children }) => {
// This is showing if the component rerenderd
useEffect(() => {
console.log(id);
});
return (
<MapIcon icon={droneIcon} position={position}>
{id}
</MapIcon>
);
};