为什么我们要在 useIsMounted 挂钩中使用回调 return 挂钩中的引用?

Why would we useCallback in useIsMounted hook to return the ref from the hook?

以下示例取自 usehooks-ts 网站

import { useCallback, useEffect, useRef } from 'react'

function useIsMounted() {
  const isMounted = useRef(false)

  useEffect(() => {
    isMounted.current = true

    return () => {
      isMounted.current = false
    }
  }, [])

  return useCallback(() => isMounted.current, [])
}

export default useIsMounted

为什么我们 return isMounted.current 作为回调而不 return 只是值 isMounted.current

什么是 return 仅将 isMounted.current 作为值的示例?

您可以自己测试不同的实现,看看会发生什么:

const UnmountingChild = ({ unmount }) => {
  const { isMounted, isMountedNC } = useIsMounted();

  useEffect(() => {
    console.log('IS MOUNTED BEFORE FETCH', isMounted()); // true
    console.log('IS MOUNTED NO CALLBACK BEFORE FETCH', isMountedNC.current); //true
    fetch('https://jsonplaceholder.typicode.com/todos/1').then((d) => {
      console.log('IS MOUNTED', isMounted()); //false
      console.log('IS MOUNTED NO CALLBACK', isMountedNC.current); //false
    });
    unmount(); // <-- This triggers the unmount of the component
  }, []);

  return <>Child</>;
};

function useIsMounted() {
  const isMounted = useRef(false);

  useEffect(() => {
    isMounted.current = true;
    return () => (isMounted.current = false);
  }, []);

  return {
    isMounted: useCallback(() => isMounted.current, []),
    isMountedNC: isMounted,
  };
}

查看演示 HERE

回调的使用很有用,因为它可以让您在需要时直接读取 refref.current 的值,如果您想要,只需调用 isMounted()直接 return ref 你只需要确保 return 所有 ref 而不仅仅是 ref.current 因为如果你通过 ref.current 你会只传递实际值而不是 mutable ref object,因此它的值将始终固定为 false。 返回 ref 会强制您每次读取 .current 属性,这不是很好,它可能会误导人们在不知道内部实现的情况下使用 hook,同时调用 isMounted() 更好读,更好用,避免使用麻烦。