简体   繁体   English

如何使用useMemo挂钩来记忆孩子

[英]How to use useMemo hook to memoize children

I have a component that renders Markers on leaflet map. 我有一个在传单地图上渲染标记的组件。 The markers need to change position every time the server sends a new position for one or more markers. 每当服务器为一个或多个标记发送新位置时,标记就需要更改位置。 How can I change the position of the specific markers that changed its position without re-render all the markers? 如何在不重新渲染所有标记的情况下更改已更改其位置的特定标记的位置?

I was thinking to use useMemo hook but I didn't succeed to use this hook on map function because hook cannot be called inside callback. 我当时在考虑使用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>
  );
};


The actual results were that every time the socket receives location it re-renders all the participants' icons instead of re-render only the first participant in the array. 实际结果是,每次套接字收到位置时,它都会重新呈现所有参与者的图标,而不是仅重新渲染数组中的第一个参与者。

Because you are updating the whole position array every render, the reference to the array representing the previous location and the current location will be different, although the latitude and longitude might be exactly the same. 因为您要在每个渲染中更新整个position数组,所以尽管纬度和经度可能完全相同,但表示先前位置和当前位置的数组的引用将有所不同。 To make it work, wrap PariticpantIcon inside React.memo , then do either one of the followings: 要使其工作, PariticpantIcon React.memo包装在React.memo ,然后执行以下任一操作:

  • Split position into 2 different props, namely lat and long . position分为2个不同的道具,即latlong Then inside ParticipantIcon you can put them back together. 然后,您可以在ParticipantIcon内部将它们放回原处。 This codesandbox explains best. codeandbox可以最好地说明。

  • Restructure the participants array. 重组participants数组。 Group lat and long together initially would prevent new reference being created at render phase. latlong在一起最初会阻止在渲染阶段创建新引用。 This codesandbox demonstrates this. codeandbox演示了这一点。

Bonus: Since the ParticipantIcon component just displays the id, you might as well make it cleaner like this: 奖励:由于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>
  );
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM