前言
使用 hook 也有一段时间了,但是 useCallback 和 useMemo 还不是傻傻分不清(虽某种程度上可以相互相当)和具体使用场景,遂整理一下。
useCallback
const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
);
返回一个 memoized 回调函数。(缓存函数)
使用方式
没有使用 useCallback ,函数 fetchData 会一直被执行:
import React, { useState, useEffect } from 'react'
export default function App() {
const [data, setData] = useState(null)
const [manualRendering, setManualRendering] = useState(1)
const handleChange = () => {
setManualRendering(manualRendering + 1)
}
const fetchData = async () => {
console.log('我是一个函数,我又被执行了。')
const res = await fetch(`https://jsonplaceholder.typicode.com/users`)
setData(res)
}
useEffect(() => {
fetchData()
}, [fetchData]) // 总之是会执行多次,但是 fetchData 只需要执行一次
return (
<div className='App'>
<h1>Hello Hooks</h1>
<button onClick={handleChange}>Re-render</button>
</div>
)
}
使用了 useCallback ,函数 fetchData 就不会一直被执行,或者会按照依赖项数组再次执行:
// 需要引入 useCallback 或者直接使用 React.useCallback(但不建议)
// const fetchData = async () => {
// console.log('我是一个函数,我又被执行了。')
// const res = await fetch(`https://jsonplaceholder.typicode.com/users`)
// setData(res)
// }
const fetchData = useCallback(async () => {
console.log('我是一个函数,我又被执行了。')
const res = await fetch(`https://jsonplaceholder.typicode.com/users`)
setData(res)
}, []) // 依赖项数组可任意添加。
useMemo
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
返回一个 memoized 值。(缓存值)
使用方式
没有使用 useMemo ,复杂函数 computeExpensiveValue 会一直被执行:
import React, { useState } from 'react'
import "./styles.css";
export default function App() {
const [manualRendering, setManualRendering] = useState(1)
// 假设为很复杂的计算
const computeExpensiveValue = () => {
console.log('我是一个值,我又被计算了。')
let newValue = 1
for (let i = 1; i < 100; i++) {
newValue = newValue * i
}
return newValue
}
const handleChange = () => {
setManualRendering(manualRendering + 1)
}
const noMemoData = computeExpensiveValue()
return (
<div className='App'>
<h1>Hello Hooks</h1>
<h2>{noMemoData}</h2>
<button onClick={handleChange}>Re-render</button>
</div>
)
}
频繁点击按钮 ,复杂函数 computeExpensiveValue 会一直执行:
使用了 useMemo ,复杂函数 computeExpensiveValue 就不会一直被执行,或者会按照依赖项数组再次执行:
// 需要引入 useMemo 或者直接使用 React.useMemo(但不建议)
// const noMemoData = computeExpensiveValue()
const useMemoData = useMemo(() => computeExpensiveValue(), []) // 依赖项数组可任意添加。
总结
某种程度上看,两者也是有很大的联系的,某种程度可以相互相当:
useCallback(fn, deps)相当于useMemo(() => fn, deps)。以上只是简单理解
useCallback和useMemo,并不是所有情况都得加上useCallback和useMemo,不合理的地方加上反倒增加性能消耗。