useCallback和useMemo返回一个memoized的回调函数或者一个memoized的值,只有当其传入的依赖项数组发生变化后才会发生改变。
useCallback
const [count, setCount] = useState(1);
const [val, setVal] = useState(1);
const callBack = useCallback(()=>{
return count;
},[count])
上面代码中我们hook了2个state,并且hook了一个useCallback,useCallback的依赖项数值只有count而没有val,那么只有当count变化后callBack 就会是一个新的方法,否则和之前的引用一直。
形象的将,当我们调用setVal后,假设之前的callBack 为c1,setVal后的callBack 为c2,那么c1 === c2
将返回true,而如果我们调用了setCount,那么c1 === c2将会返回false,正如官网文档中所说:把回调函数传递给经过优化的并使用引用相等性去避免非必要渲染(例如 shouldComponentUpdate)的子组件时,它将非常有用。
useMemo
useMemo和useCallback非常相似,并且useCallback(fn, deps) 和 useMemo(() => fn, deps)是等价的。
const [count, setCount] = useState(1);
const [val, setVal] = useState(1);
let memoizedVal = useMemo(()=>{
console.log("------val------", val);
return(`${count} test ${val}`);
},[val])
上面的代码useMemo的依赖项数值为val,那么仅当val值发生变化后useMemo的函数才会执行,并且返回一个新的memoizedVal 值,如果val没有变化,useMemo的函数不会执行,memoizedVal 仍是之前的值,即便我们调用了setCount,组件会重新渲染,但是由于val没有变化,useMemo的函数不会执行,memoizedVal 仍是之前的值。
useMemo与vue的conputed相似,可以通过一个依赖项数值,实时计算出另外一个值,并且useMemo是一个react优化性能的方式,可以通过useCallback和useMemo避免不少的无必要操作。不过需要注意的时,useMemo中不应该操作dom,比如使用setVal。因为这将导致死循环。这类副作用操作应该放到useEffect中