【问题标题】:Update UI using Custom Hook使用自定义 Hook 更新 UI
【发布时间】:2021-08-25 08:52:49
【问题描述】:

我正在尝试使用自定义挂钩,并且我还实现了一个自定义挂钩,但是在执行删除操作和再次获取用户的情况下遇到问题。

第一次获取用户很好,但我如何处理删除用户和再次获取用户的场景并在 API 进行时显示加载器?

我可能错误地使用了 App 组件。谁能帮我解决这个问题,我怎样才能达到预期的效果?

谢谢

代码:

export interface APIStatus {
  status: 'loading' | 'error' | 'done';
}

export const useFetch = (api, params) => {
  const [data, setData] = useState([]);
  const [apiStatus, setApiStatus] = useState<APIStatus>({ status: 'loading' });
  const [isSignedIn] = getSignInStatus();

  const fetchData = useCallback(async () => {
    try {
      const {data} = await api(params);
      setData(data);
    } catch (err) {
      setApiStatus({ status: 'error' });
    } finally {
      setApiStatus({ status: 'done' });
    }
  }, [api]);

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

  return { apiStatus, data };
};

//App.tsx
export const App: React.FC = () => {
  const { apiStatus, data } = useFetch(apis.fetchUsers, "limit=100");

  const deleteUser = (id) => {
    const { apiStatus, data } = useFetch(apis.deleteUser, `id=${id}`);
    // 1. apiStatus is only available inside. I cannot access it in return and show loader

    if (data.status){
      // 2. How can I call the fetchUsers API again as I cannot call the useFetch hook inside if block
    }
  }

  return(
    <>
      {apiStatus.status === 'loading' ? <ShowLoader /> : data.map(user => <div key={user.id} onClick={() => deleteUser(user.id)}> {user.name} </div>)}
    </>
  )
}

【问题讨论】:

    标签: reactjs typescript react-hooks


    【解决方案1】:

    您不应该在 deleteUser 挂钩中使用 useFetch 。这违反了钩子的规则,因为钩子总是需要位于功能组件的顶部。

    您可以做的是,您可以将一个名为 shouldRefetch 的附加参数传递给您的 customHook,并将其作为依赖项添加到您的 useEffect 中。

    import { useEffect, useState } from "react";
    
    export interface APIStatus {
      status: "loading" | "error" | "done";
    }
    
    // add shouldRefetch as the argument to the custom hook
    export const useFetch = (api, params, shouldRefetch) => {
      const [data, setData] = useState([]);
      const [apiStatus, setApiStatus] = useState(null);
      const [isSignedIn] = getSignInStatus();
    
      const fetchData = useCallback(async () => {
        setApiStatus({ status: "loading" });
        try {
          const { data } = await api(params);
          setData(data);
        } catch (err) {
          setApiStatus({ status: "error" });
        } finally {
          setApiStatus({ status: "done" });
        }
      }, [api]);
    
      // Add the shouldRefetch as an dependency and fire the API call when it is true
      useEffect(() => {
        if (isSignedIn || shouldRefetch) fetchData();
      }, [isSignedIn, shouldRefetch]);
    
      return { apiStatus, data };
    };
    
    //App.tsx
    export const App: React.FC = () => {
      const [shouldRefetch, setShouldRefetch] = useState(false);
      const { apiStatus, data } = useFetch(
        apis.fetchUsers,
        "limit=100",
        shouldRefetch
      );
    
      const deleteUser = (id) => {
        // delete the user
    
        // now set the shouldRefetch state to true
        setShouldRefetch(true);
      };
    
      // when the API status is done or error and the shouldRefetch is true then change it to false
      useEffect(() => {
        if (
          (apiStatus.status === "done" || apiStatus.status === "error") &&
          shouldRefetch
        ) {
          setShouldRefetch(false);
        }
      }, [apiStatus.status, shouldRefetch]);
    
      return (
        <>
          {apiStatus.status === "loading" ? (
            <ShowLoader />
          ) : (
            data.map((user) => (
              <div key={user.id} onClick={() => deleteUser(user.id)}>
                {" "}
                {user.name}{" "}
              </div>
            ))
          )}
        </>
      );
    };
    

    【讨论】:

    • 非常感谢您的帮助。但是我将如何处理deleteUser 功能。我想使用 useFetch 挂钩进行删除,但如果我在 deleteUser() 函数中使用它,我将无法在删除 API 正在进行时显示 &lt;ShowLoader /&gt; 组件?
    • 好的,明白了。在那种情况下,我认为你需要有类似的东西 - react-query.tanstack.com/guides/mutations 。你的钩子应该暴露一个可以在以后调用的函数。在您删除用户的情况下。如果您有权添加其他工具,那么我强烈建议您尝试我们的 react-query。因为它与您正在寻找的东西完全相同,但以更有效的方式处理缓存、重新获取等。
    • 好的,非常感谢,我会调查的 :)
    猜你喜欢
    • 2021-05-04
    • 1970-01-01
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 2020-01-08
    相关资源
    最近更新 更多