【问题标题】:Why custom hook returns results twice为什么自定义钩子返回结果两次
【发布时间】:2020-04-20 04:24:38
【问题描述】:

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

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>
  )

【问题讨论】:

  • 您希望发生什么?

标签: reactjs react-hooks


【解决方案1】:

您的finally 块在try 块之后触发。

请注意,无论是否抛出异常,finally 块都会执行。

The finally block

【讨论】:

    【解决方案2】:

    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感兴趣

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

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

    【讨论】:

    • 因此所有状态更新都将被返回,除非它是事件处理程序或生命周期方法。好的,我猜想状态更新已返回。是否有此文档链接。我知道每个人都希望它像这样工作,但作为一个新手,我很惊讶。
    • 这是一个内部实现,所以你不应该考虑它,你可以阅读更多here
    • 好的,谢谢,所以如果我将逻辑从 fetchdata 中移出,更新将被批量处理,整个事情都会中断,我会试试的。
    • 这不是我提到的旁注的解决方案,如何解决它超出了当前问题的范围。
    • 是的,我指的不是旁注,而是我对批处理与非批处理行为的理解。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-20
    • 2017-07-19
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多