简体   繁体   English

在useEffect中使用memoized object时可以使用useMemo吗?

[英]Can we use useMemo when memoized object is used in useEffect?

Imagine this case.想象一下这种情况。

A hook that receives an object and based on the object's properties does some computing and returns the result.接收 object 并根据对象的属性进行一些计算并返回结果的钩子。

export const useTestHook = (someOject) => {
  const [updated, set] = useState({ val1: null, val2: null });

  useEffect(() => {
    set({
      val1: `${someOject.val1}_-`,
      val2: `${someOject.val2}_-`,
    })
  }, [someOject]);

  return updated;
}

The component using the hook has these values separated so a new object needs to be initialized so it can be passed to the hook.使用钩子的组件将这些值分开,因此需要初始化新的 object 以便将其传递给钩子。 The result of the hook is then passed via some callback back to the parent.然后通过一些回调将钩子的结果传递回父级。

function TestComp({ onChange, parentValue }) {
  const [value1, setValue1] = useState('value1');
  const [value2, setValue2] = useState('value2');

  // since mergedValues is used as dependency of the hook I need to 'memoize' it otherwise it gets 
  // recreated on each re-render and will cycle 
  const mergedValues = useMemo(() => ({
    val1: value1,
    val2: value2
  }), [value1, value2]);

  const updatedVals = useTestHook(mergedValues);

  useEffect(() => {
    onChange(updatedVals);
  }, [onChange, updatedVals]);

  return (
    <div>
      Hello
    </div>
  );
}

The parent can do some other computing on that value and the result returns back to the child.父级可以对该值进行一些其他计算,并将结果返回给子级。

function App() {
  const [value, set] = useState('value1');

  return (
    <TestComp onChange={set} parentValue={value} />
  );
}

What is the correct way to handle object creation in a react component when the object is used as a dependency of some effect?当 object 用作某些效果的依赖项时,在反应组件中处理 object 创建的正确方法是什么? Can be the useMemo hook used for it?可以使用useMemo钩子吗?

const mergedValues = useMemo(() => ({
    val1: value1,
    val2: value2
  }), [value1, value2]);

Official docs say "You may rely on useMemo as a performance optimization, not as a semantic guarantee."官方文档说“你可能依赖 useMemo 作为性能优化,而不是语义保证。” https://reactjs.org/docs/hooks-reference.html#usememo https://reactjs.org/docs/hooks-reference.html#usememo

Another way would be changing the hook's prop from an object to simple values and creating the object from these values inside hook's useEffect but this approach is no go for me.另一种方法是将钩子的道具从 object 更改为简单值,并从钩子的 useEffect 中的这些值创建 object 但这种方法对我来说不是 go。

What is the correct way to handle object creation in a react component when the object is used as a dependency of some effect?当 object 用作某些效果的依赖项时,在反应组件中处理 object 创建的正确方法是什么? Can be the useMemo hook used for it?可以使用 useMemo 钩子吗?

Yes you can use useMemo but there is one caveat.是的,您可以使用useMemo ,但有一个警告。 Since the docs say this:由于文档是这样说的:

You may rely on useMemo as a performance optimization, not as a semantic guarantee.您可能依赖 useMemo 作为性能优化,而不是语义保证。 In the future, React may choose to “forget” some previously memoized values and recalculate them on next rende将来,React 可能会选择“忘记”一些以前记忆的值,并在下一次渲染时重新计算它们

It means in some cases useMemo can forget its stored value and still give you a new object, which could make useEffect to fire if it uses that object as dependency, and that might be not what you want.这意味着在某些情况下useMemo可以忘记它的存储值,并且仍然给你一个新的 object,如果它使用 object 作为依赖项,它可能会触发useEffect ,这可能不是你想要的。 But if your useEffect is such that overfiring is not an issue, then this is not a problem.但是,如果您的useEffect使得过度燃烧不是问题,那么这不是问题。

You can also do something like this and there will be no need for useMemo (assuming val1 and val2 are primitives):你也可以这样做,并且不需要useMemo (假设val1val2是原语):

  useEffect(() => {
    set({
      val1: `${someOject.val1}_-`,
      val2: `${someOject.val2}_-`,
    })
  }, [someOject.val1, someOject.val2]);

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

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