useMemo hook

useMemo hook
useMemo 是个可以在重渲染的过程中缓存计算结果的 React Hook。memo 使用方法为:
const cachedValue = useMemo(calculateValue, dependencies);
其中 calculateValue 是一个计算过的值,一般的用法是一个由返回值的函数,dependencies 是一个包含所有需要监控参数的数组,这个数组对于整个 memo 的过程来说非常的重要。useMemo 在第一次渲染时会返回 calculateValue,在其他的渲染过程中,如果 dependencies 产生变化,那么就会重新调用 calculateValue 函数,并返回重新计算过的值。
这其实也算是一个 gocha,因为之前项目中出现了一个 bug 就是由 useMomo 造成的。
大概流程是使用 useMemo 缓存了一个值传到了公司内部开发的 UI 库中,UI 库返回了正确的数值,但是在我们使用的 wrapper 中,该值被 cache 了,因此 dependency 没有变化的情况下它就不会被重新渲染。
大概的案例如下:
const UIWrapper = ({ initialValue }) => {const [value, setValue] = useState(initialValue);const cachedValue = useMemo(() => 'some value here', [initialValue]);const handleUpdateVal = (someVal) => {setValue(someVal);};return <UI cachedValue={cachedValue} handleUpdateVal={handleUpdateVal} />;
};
其中 cachedValue 和 value 大概是在 UI 库中有一些依存关系,因此尽管 handleUpdateVal 中需要获取的值在 UI 中更新了,但是 handleUpdateVal 本身并没有被调用。因此,在使用第三方库时,使用 memoization 这个技巧还是需要更加的谨慎,并且需要判断数据之间是否存在依存关系,否则就有可能造成页面的不渲染。
其他一些 useMemo 的注意点
- 
useMemo使用 Object.is() 进行判断因此如果传入的值是一个对象,那么
useMemo依旧进行重新计算,如:const obj = { a: 'a' };console.log(Object.is(obj, { a: 'a' }));
所以
useMemo中不应该传入传入useState创建的对象——每次渲染useState都会创建一个新的对象,因此将这个值放入useMemo的依赖中就没有任何的意义。解决方案:可以使用
useMemo去 memo 通过useState创建的对象本身。 - 
useState可以用来 memo React 组件 - 
如果要使用
useMemo去 memo 一个函数,不如使用 useCallback - 
严格模式下 React 会渲染组件两次去判断函数是否为纯函数,这也是一个很好的 debug 方法去判断函数的输入和输出是否一致
 - 
useMemo只因惊觉 🐔 你太美作为一个性能提升的方法,如果不使用useMemo代码就无法正常工作,那么应该找到问题的关键,而不是依赖于useMemoYou should only rely on
useMemoas a performance optimization. If your code doesn’t work without it, find the underlying problem and fix it first. Then you may adduseMemoto improve performance. 


