Javascript 如何使用React中的useMemo优化我的代码?
我在使用Javascript 如何使用React中的useMemo优化我的代码?,javascript,arrays,reactjs,lodash,Javascript,Arrays,Reactjs,Lodash,我在使用useMemo()hook时遇到了一种情况 我有一个名为a的数组对象。此对象包含多个对象。这个阵列很大。当它包含b和c对象时,a看起来像a=[b,c]。我正在数组a上进行大量计算。以下是我的代码片段: const computedValue = useMemo(() => { return a.map(key,() => { anotherHighComputationFunc(key); }); },
useMemo()
hook时遇到了一种情况
我有一个名为a
的数组对象。此对象包含多个对象。这个阵列很大。当它包含b
和c
对象时,a
看起来像a=[b,c]
。我正在数组a
上进行大量计算。以下是我的代码片段:
const computedValue = useMemo(() => {
return a.map(key,() => {
anotherHighComputationFunc(key);
});
},[a])
const anotherHighComputationFunc = useMemo((key) => {
// ..... do some expensive computation
return someValue;
},[key]);
如果a
的引用没有更改,我不会再次计算该值,我只返回预计算的值。如果a
的引用发生变化,那么我将查看数组a
,以检查数组中的某个键是否改变了其引用。如果某个键的引用没有更改,则返回该键的预计算值,否则对该键执行计算
问题是hook规则失败了,因为我在另一个hook中使用了一个hook。所以它给了我一个错误。有没有其他方法可以在两个级别进行记忆?钩子规则明确规定:不要在循环、条件或嵌套函数中调用钩子。相反,总是在React函数的顶层使用钩子 创建一个存储函数值的
缓存
对象,如果它位于缓存对象内,则返回它,而不是为另一个HighComputationFunc
使用钩子
const cache = {};
function anotherHighComputationFunc(key) {
if (cache[key]) return cache[key];
/** anotherHighComputation calculation here */
cache[key] = anotherHighComputationValue;
return anotherHighComputationValue
}
const computedValue = useMemo(() => {
return a.map(key,() => {
anotherHighComputationFunc(key);
});
},[a])
useMemo()
钩子在这里对您没有帮助,因为它的缓存大小为1,您不能调用其他钩子中的钩子。此外,您不需要记忆函数,只需要记忆调用的结果
您可以使用创建一个简单的memonization包装器,它将允许垃圾收集器在不需要时清理这些值
注意:WeakMap键必须是对象
const weakMemo = fn => {
const map = new WeakMap();
return obj => {
if (map.has(obj)) return map.get(obj);
const res = fn(obj);
map.set(obj, res);
return rs;
}
};
// the useMemo is needed here to preserve the instance of the memoized function with the cached values
const computeKey = useMemo(() => weakMemo((key) => {
// ..... do some expensive computation
return someValue;
}), [anotherHighComputationFunc]);
const computedValue = useMemo(() => a.map(computeKey), [a, computeKey]);
钩子可以在其他钩子中使用,但我怀疑问题在于某些“条件”钩子调用,尽管我没有从您的代码片段中看到钩子是在另一个钩子中调用的。你能提供一个更完整的代码示例吗?@drewerese我认为问题在于调用useMemo inside map函数,它是一个循环,React要求避免在循环中使用钩子。也许,它被认为是在循环中调用的(但你调用的是memozied回调),或者是从嵌套函数调用的(我认为就是这个)。听起来你可以直接滚动你自己的简单缓存。这是最好的方法。但这里的问题是,我必须维护自己的缓存,而缓存的效率可能不如useMemo。如果有其他方法可以避免创建我自己的缓存,并使用一些已经实现的最好的记忆技术。你所说的
我自己的缓存可能不如useMemo的效率是什么意思?对象查找具有O(1)
时间复杂性。您能详细说明一下这里的更高效的是什么意思吗?高效的意思是,必须定期清理内存,这样我的内存大部分不会被缓存对象占用。React在其网站useMemo上也提到:将来,React可能会选择“忘记”一些以前记忆的值,并在下一次渲染时重新计算它们,例如,为屏幕外组件释放内存,然后只需useRef
收集值并将其用作缓存。我已经更新了上面的代码。所谓的“规则”,声明不要在循环、条件或嵌套函数中调用钩子。相反,始终在React函数的顶层使用钩子。
,无论如何都不会被违反AnotherHighComputeFunc
不是钩子,它是钩子返回的值,“规则”不适用于该值。