为什么React.useCallback触发器重新呈现,但不应该重新呈现?

时间:2019-12-23 13:55:52

标签: javascript reactjs react-hooks

我将Redux连接到绑定了onClick动作的组件。尽管我使用useCallback挂钩,但每次单击它都会重新渲染。这是我的简化组件:

const Map = props => {
  const dispatch = useDispatch(); // from react-redux
  const coordinates = useSelector(state => state.track.coordinates); // from react-redux
  const onClick = useCallback( // from react
    data => {
      return dispatch({type: 'ADD_COORDINATES', payload: data});
    },
    [dispatch]
  );

  return (
    <div className="Map">
      <GoogleMap
        onClick={onClick}>
        <Track
          coordinates={coordinates}
        />
      </GoogleMap>
    </div>
  );
};

1 个答案:

答案 0 :(得分:1)

在不提供任何其他上下文的情况下,并且该组件确实是“简化的”(没有其他可能导致渲染的内容),Map组件将仅在其父渲染器上重新渲染:

const Parent = () => {
  const coordinates = useSelector(coordinatesSelector);
  return <Map />;
};

在调度addCoordinates动作时,您可以触发其父项。

您应该尝试使用memoize Map组件:

  

如果给定相同的道具,功能组件呈现相同的结果,则可以将其包装在对React.memo的调用中,以在某些情况下通过记忆结果来提高性能。这意味着React将跳过渲染组件,并重新使用最后渲染的结果。

 const Map = () => {
  ...
  return ....;
};

export default React.memo(Map);

问题更新后进行编辑:

您的组件由于useSelector重新呈现为stated in the docs:

  

调度一个动作时,useSelector()将对前一个选择器结果值和当前结果值进行参考比较。如果它们不同,则将强制重新渲染组件。如果它们相同,则组件将不会重新渲染。

因此,您可能要添加其他equalityFn

const coordinates = useSelector(state => state.track.coordinates, areSameCoords)