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

问题描述 投票:0回答:2

想象一下这个案例。

接收对象并根据对象的属性进行一些计算并返回结果的钩子。

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

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

  return updated;
}

使用钩子的组件将这些值分开,因此需要初始化一个新对象,以便将其传递给钩子。然后,钩子的结果通过一些回调传递回父级。

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

父级可以对该值进行其他一些计算,并将结果返回给子级。

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

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

当对象用作某些效果的依赖项时,在反应组件中处理对象创建的正确方法是什么?可以用

useMemo
钩子吗?

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

官方文档说 “您可以依赖 useMemo 作为性能优化,而不是语义保证。” https://reactjs.org/docs/hooks-reference.html#usememo

另一种方法是将钩子的 prop 从对象更改为简单值,并在钩子的 useEffect 内从这些值创建对象,但这种方法不适合我。

reactjs react-hooks react-usememo
2个回答
1
投票

在 React 组件中处理对象创建的正确方法是什么 当对象用作某种效果的依赖项时?可以是 useMemo 钩子用于它吗?

是的,您可以使用

useMemo
,但有一个警告。既然文档这么说:

您可以依赖 useMemo 作为性能优化,而不是作为 语义保证。将来,React 可能会选择“忘记”一些之前记忆的值,并在下一个 rende 时重新计算它们

这意味着在某些情况下

useMemo
可能会忘记其存储的值,但仍然会为您提供一个新对象,如果它使用该对象作为依赖项,这可能会使
useEffect
触发,而这可能不是您想要的。但如果您的
useEffect
不存在过火问题,那么这也不是问题。

您也可以这样做,并且不需要

useMemo
(假设
val1
val2
是原语):

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

0
投票

在不可避免的用例中,我最终会用不确定的键/对值来记忆对象。因此,在不知道其键名或对象内部是否有子对象的情况下无法提取 - typescript - 使用泛型定义形状

我通常使用

JSON.stringify
将对象展平为字符串类型并将其用作依赖项。此解决方案应该是最后的手段,如下面的注意部分所述。

function MyComponent({ nestedObj }: Props) {
  useMemo(() => {
    // do something with nestedObj
  }, [nestedObj && JSON.stringify(nestedObj)])

  useEffect(() => {
    // do something with nestedObj
  }, [nestedObj && JSON.stringify(nestedObj)])
}

注意:不建议传递任意对象或深层嵌套对象。始终解构对其基本数据类型的依赖关系并将其作为依赖关系传递。重新设计逻辑以使其简单,因为记忆的成本很高。不要传递日期对象符号函数引用。会造成不良影响。

© www.soinside.com 2019 - 2024. All rights reserved.