命名

Hook 的名称必须以 use 开头,然后紧跟一个大写字母。(反之,如果创建的函数没有调用任何 Hook 方法,在命名时应避免使用 use 前缀)

执行时机

每当组件重新渲染,自定义 Hook 中的代码就会重新运行

什么时候使用

  • 多个组件共享相同逻辑时,可以提取该逻辑到自定义 Hook
  • 复杂组件逻辑需要拆分时,当组件变得过于复杂时,可以使用自定义 Hook 将其拆分为更小的函数
  • 每当写 useEffect 时,考虑一下把它包裹在自定义 Hook 是否更清晰,随着时间的推移,应用中大部分 Effect 都会存在于自定义 Hook 内部

如,抽出公共请求数据逻辑:

function useData(url) {
  const [data, setData] = useState(null);
  useEffect(() => {
    if (url) {
      let ignore = false;
      fetch(url)
        .then(response => response.json())
        .then(json => {
          if (!ignore) {
            setData(json);
          }
        });
        
      // 添加一个 清理函数 来忽略较早的返回结果(处理竞态问题),确保了当你在 Effect 中获取数据时,除了最后一次请求的所有返回结果都将被忽略
      return () => {
        ignore = true;
      };
    }
  }, [url]);
  return data;
}