[英]How would you implement useCallback using useState from scratch?
This is how I have implemented it.这就是我实施它的方式。 Does this look ok?这看起来好吗?
function useCallback(fn, deps) {
const [state, setState] = useState({ fn });
useEffect(() => {
setState({ fn });
}, deps);
return state.fn;
}
Nice try but not perfect.不错的尝试,但并不完美。 Your implementation calls setState()
which triggers another round of re-render of component, that doesn't match up to the behavior of the real useCallback()
hook.您的实现调用setState()
触发另一轮重新渲染组件,这与真正的useCallback()
钩子的行为不匹配。
OK challenge accepted. OK 接受挑战。
Actually useState()
isn't a good building block for implementing useCallback()
, useRef()
is better.实际上useState()
不是实现useCallback()
的好构建块, useRef()
更好。 But to meet your requirement, lemme first write useRef()
with useState()
.但是为了满足您的要求,让我先用useRef()
编写useState()
。
function useRef(value) {
const [ref] = useState({ current: value })
ref.current = value
return ref
}
Easy piecy.易碎。 We don't need useEffect()
.我们不需要useEffect()
。 All we want is just a function to compare the deps between re-render and see if they change.我们想要的只是一个函数来比较重新渲染之间的深度并查看它们是否发生变化。
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
}
Now we can implement useCallback()
现在我们可以实现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]
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.