首页 > 解决方案 > 为什么自定义钩子返回结果两次

问题描述

下面的帖子是关于创建一个用于获取数据的自定义钩子,它很简单。

https://dev.to/patrixr/react-writing-a-custom-api-hook-l16

虽然有一部分我不明白它是如何工作的。

为什么这个钩子会返回两次结果?(isLoading=true isLoading=false)

function useAPI(method, ...params) {
    // ---- State
    const [data, setData]           = useState(null);
    const [isLoading, setIsLoading] = useState(false);
    const [error, setError]         = useState(null);

    // ---- API
    const fetchData = async () => {
      onError(null);
      try {
        setIsLoading(true);
        setData(await APIService[method](...params));
      } catch (e) {
        setError(e);
      } finally {
        setIsLoading(false);
      }
    };

    useEffect(() => { fetchData() }, []);

    return [ data, isLoading, error, fetchData ];
}


function HomeScreen() {
  const [ users, isLoading, error, retry ] = useAPI('loadUsers');

  // --- Display error
  if (error) {
    return <ErrorPopup msg={error.message} retryCb={retry}></ErrorPopup>
  }

  // --- Template
  return (
    <View>
      <LoadingSpinner loading={isLoading}></LoadingSpinner>
      {
          (users && users.length > 0) &&
            <UserList users={users}></UserList>
      }
    </View>
  )

标签: reactjsreact-hooks

解决方案


React 在事件处理程序生命周期方法中批量状态更新。

fetchData不是其中的任何一个,因此不会发生批处理。

现在,调用时fetchData()

const fetchData = async () => {
  onError(null);
  try {
    // #1 async setState
    setIsLoading(true);

    const data = await APIService[method](...params);

    // #2 async setState
    setData(data);

  } catch (e) {
    setError(e);
  } finally {

    // #3 async setState
    setIsLoading(false);
  }
};

成功时,有3异步事件,我们只对它感兴趣#1并且#3

  • 将加载状态设置为true默认值false
  • 将加载状态设置false#1async setState

旁注:乍一看,这个钩子有缺陷,fetchData在每次渲染时都会重新分配,你会收到缺少依赖项的警告。


推荐阅读