简体   繁体   English

将带有参数的匿名函数传递给包裹在备忘录中的子组件

[英]Passing anonymous function with a parameter to child component wrapped in memo

I have a component Marker , which I don't want to rerender unless really needed.我有一个组件Marker ,除非真的需要,否则我不想重新渲染它。

So it's wrapped in a memo hook, but since one of the props is an anonymous function, then the Marker still rerenders every time it's parent rerenders.所以它被包裹在一个备忘录钩子中,但由于其中一个道具是一个匿名函数,所以每次它的父级重新渲染时,标记仍然会重新渲染。

Now, this would have a simple solution of just wrapping the passed in function prop in useCallback hook, but since the function also takes a parameter, then I'm bit stuck in finding a nice solution.现在,这将有一个简单的解决方案,只需将传入的函数 prop 包装在 useCallback 挂钩中,但由于该函数也有一个参数,所以我很难找到一个好的解决方案。 Memoizing the passed in function in a parent component with useMemo also will not work because of that parameter.由于该参数,使用 useMemo 在父组件中记忆传入的函数也将不起作用。

const Map = () => {
  ...
  ...
  return(
    {markers.map(marker => {
        <Marker {...props} onPress={() => selectMarker(marker.id)}
    })
  )
}

const Marker = (...props, onPress) => {
    ... memoized function that at some point calls onPress()
}

The most simple solution for this is to pass all the required arguments from the Marker component itself.最简单的解决方案是从 Marker 组件本身传递所有必需的参数。 With this change, you can make the onPress handler pure.通过此更改,您可以使onPress处理程序变得纯粹。

const Map = () => {
  const handleMarkerPress = useCallback((markerId) => {
    selectMarker(markerId);
  }, []);

  return(
    {markers.map(marker => {
        <Marker {...props} marker={marker} onPress={handleMarkerPress}
    })
  )
}

const Marker = (...props, marker, onPress) => {
   return <div onClick={() => onPress(marker.id)}>...</div>;
}

Try to use the useCallback hook in the parent component to create the onPress function, and pass the marker.id as an argument to the callback.尝试在父组件中使用 useCallback 钩子来创建 onPress 函数,并将 marker.id 作为参数传递给回调。 This way, the function will only be recreated if the marker.id value changes, and the Marker component will not re-render unnecessarily.这样,只有当 marker.id 值发生变化时才会重新创建该函数,并且 Marker 组件不会不必要地重新渲染。

Here's how you could do this:以下是您可以如何做到这一点:

const Map = () => {
  ...
  ...
  const selectMarker = useCallback((id) => {
    // do something with the marker id
  }, []);

  return(
    {markers.map(marker => {
        <Marker {...props} onPress={() => selectMarker(marker.id)}
    })
  )
}

const Marker = ({ onPress }) => {
    ...
    ...
    // call onPress when necessary
    onPress();
}

The useCallback hook will return a memoized version of the selectMarker function that only changes if the values in the dependency array (in this case, an empty array) change. useCallback 挂钩将返回 selectMarker 函数的记忆版本,该函数仅在依赖数组(在本例中为空数组)中的值发生变化时才会发生变化。 Since the selectMarker function is being passed as a prop to the Marker component, the Marker component will only re-render if the selectMarker function changes, which will only happen if the marker.id value changes.由于 selectMarker 函数作为 prop 传递给 Marker 组件,Marker 组件只会在 selectMarker 函数发生变化时重新渲染,这只会在 marker.id 值发生变化时发生。

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

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