想象一下这个案例。
接收对象并根据对象的属性进行一些计算并返回结果的钩子。
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 内从这些值创建对象,但这种方法不适合我。
在 React 组件中处理对象创建的正确方法是什么 当对象用作某种效果的依赖项时?可以是 useMemo 钩子用于它吗?
是的,您可以使用
useMemo
,但有一个警告。既然文档这么说:
您可以依赖 useMemo 作为性能优化,而不是作为 语义保证。将来,React 可能会选择“忘记”一些之前记忆的值,并在下一个 rende 时重新计算它们
这意味着在某些情况下
useMemo
可能会忘记其存储的值,但仍然会为您提供一个新对象,如果它使用该对象作为依赖项,这可能会使 useEffect
触发,而这可能不是您想要的。但如果您的 useEffect
不存在过火问题,那么这也不是问题。
您也可以这样做,并且不需要
useMemo
(假设val1
和val2
是原语):
useEffect(() => {
set({
val1: `${someOject.val1}_-`,
val2: `${someOject.val2}_-`,
})
}, [someOject.val1, someOject.val2]);
在不可避免的用例中,我最终会用不确定的键/对值来记忆对象。因此,在不知道其键名或对象内部是否有子对象的情况下无法提取 - (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)])
}
注意:不建议传递任意对象或深层嵌套对象。始终解构对其基本数据类型的依赖关系并将其作为依赖关系传递。重新设计逻辑以使其简单,因为记忆的成本很高。不要传递日期对象、符号或函数引用。会造成不良影响。