如何从头开始使用 useState 实现 useCallback?

use*_*951 2 reactjs react-hooks

我就是这样实现的。这看起来还好吗?

function useCallback(fn, deps) {
    const [state, setState] = useState({ fn });

    useEffect(() => {
        setState({ fn });
    }, deps);

    return state.fn;
}
Run Code Online (Sandbox Code Playgroud)

hac*_*ape 5

不错的尝试,但并不完美。您的实现调用会setState()触发组件的另一轮重新渲染,这与真实的行为不匹配useCallback()钩子的行为不匹配。

\n

好的挑战已接受。

\n

实际上,useState()\xe2\x80\x99 不是一个很好的实现useCallback(),useRef()更好的构建块。但为了满足你的要求,让我先useRef()useState()写。

\n
function useRef(value) {\n  const [ref] = useState({ current: value })\n  ref.current = value\n  return ref\n}\n
Run Code Online (Sandbox Code Playgroud)\n

简单的碎片。我们不需要\xe2\x80\x99tuseEffect()。我们想要的只是一个比较重新渲染之间的依赖关系并查看它们是否发生变化的函数。

\n
function depsChanged(deps1, deps2) {\n  if (deps1 === undefined || deps2 === undefined) return true\n  if (deps1.length !== deps2.length) return true\n  for (let i in deps1) {\n    if (!Object.is(deps1[i], deps2[i])) return true\n  }\n  return false\n}\n
Run Code Online (Sandbox Code Playgroud)\n

现在我们可以实施useCallback()

\n
function useCallback(fn, deps) {\n  const slots = useRef([fn, deps]).current\n  if (depsChanged(slots[1], deps)) {\n    slots[0] = fn\n  }\n  slots[1] = deps\n  return slots[0]\n}\n
Run Code Online (Sandbox Code Playgroud)\n