这就是我实现它的方式。这样看起来还好吗?
function useCallback(fn, deps) {
const [state, setState] = useState({ fn });
useEffect(() => {
setState({ fn });
}, deps);
return state.fn;
}
答案 0 :(得分:1)
不错的尝试,但并不完美。您的实现调用setState()
会触发另一轮组件的重新渲染,这与真实的useCallback()
挂钩的行为不符。
接受确定的挑战。
实际上,useState()
并不是实施useCallback()
的良好基础,useRef()
更好。但是为了满足您的要求,lemme首先用useRef()
写useState()
。
function useRef(value) {
const [ref] = useState({ current: value })
ref.current = value
return ref
}
轻松虔诚。我们不需要useEffect()
。我们只需要一个函数来比较重新渲染之间的深度,看看它们是否改变。
function depsChanged(deps1, deps2) {
if (deps1 === undefined || deps2 === undefined) return true
if (deps1.length !== deps2.length) return true
for (let i in deps1) {
if (!Object.is(deps1[i], deps2[i])) return true
}
return false
}
现在我们可以实现useCallback()
function useCallback(fn, deps) {
const slots = useRef([fn, deps]).current
if (depsChanged(slots[1], deps)) {
slots[0] = fn
}
slots[1] = deps
return slots[0]
}