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
不是钩子,它是钩子返回的值,“规则”不适用于该值。