简体   繁体   English

为什么 React.useCallback 触发重新渲染,你不应该?

[英]Why does React.useCallback trigger rerender, thouh it should not?

I have redux connected Component with onClick action bound to it.我将 redux 连接的组件与绑定到它的 onClick 操作。 Every time I click it rerenders, though I use useCallback hook.每次我点击它都会重新渲染,尽管我使用了useCallback钩子。 Here is my simplified component:这是我的简化组件:

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>
  );
};

Without giving any additional context, and that the component is really "simplified" (there is nothing else that may cause a render), Map component will re-render only on its parent render:没有给出任何额外的上下文,并且组件确实“简化”了(没有其他可能导致渲染的东西), Map组件将仅在其父渲染上重新渲染:

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

On dispatching addCoordinates action you may trigger its parent.在调度addCoordinates操作时,您可能会触发其父级。

You should try and memoize the Map component:你应该尝试memoize的Map组件:

If your function component renders the same result given the same props, you can wrap it in a call to React.memo for a performance boost in some cases by memoizing the result.如果您的函数组件在给定相同的 props 的情况下呈现相同的结果,您可以将其包装在对 React.memo 的调用中,以便在某些情况下通过记忆结果来提高性能。 This means that React will skip rendering the component, and reuse the last rendered result.这意味着 React 将跳过渲染组件,并重用上次渲染的结果。

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

export default React.memo(Map);

Edit after question update:问题更新后编辑:

Your component re-renders due to useSelector as stated in the docs:您的组件由于文档中所述的useSelector重新渲染

When an action is dispatched, useSelector() will do a reference comparison of the previous selector result value and the current result value.当一个动作被分派时,useSelector() 将对前一个选择器结果值和当前结果值进行引用比较。 If they are different, the component will be forced to re-render.如果它们不同,组件将被迫重新渲染。 If they are the same, the component will not re-render.如果它们相同,则组件不会重新渲染。

Therefore, you might want to add additional equalityFn :因此,您可能需要添加额外的equalityFn

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

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

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