【问题标题】:useApi hook with params带参数的 useApi 钩子
【发布时间】:2020-03-19 05:51:24
【问题描述】:

我正在尝试使用useApi hook with multiple parameters 的第一个答案中描述的钩子 useAPI 但我有一个主要问题。在我的组件中,我在 url 本身中有可能没有值的参数时呈现 useAPI,这会导致错误。这些值来自不同的 API 调用。如何在定义参数时使用 only 渲染我的 useAPI 钩子?

我的代码如下所示:

const Availability = () => {
     [account, setAccount] = useState(0);
     const savedApiData = useAPI({
         endpoint:'/programs/${state.account.id}/', // The account obj comes from a different useAPI in this component
         requestType: 'POST',
         body: {
            siteIds: !state.siteId ? [] : [state.siteId] 
         }
     }); 
}

在第一次渲染时,API url 将显示“无法读取未定义的属性“id””的错误。

【问题讨论】:

    标签: reactjs api react-hooks


    【解决方案1】:

    这真的很简单,在第四行,你访问的是state.accountid 属性,但是这里的account 是未定义的(可能是因为它不存在)。为了解决这个问题,你可以在 state.account 未定义时使用一个虚拟 id(但你肯定会从服务器得到一个 404,所以你必须处理它),或者根本不使用 useApi。钩子真的很难修补,有时一个小的未处理的钩子用例可能会使其完全无用。

    另一个想法可能是允许endpoint钩子配置参数成为一个函数(仅在请求时调用),并向该对象添加另一个布尔参数以控制是否应该完成请求。

    然后,如果state.account未定义,则没有请求完成,endpoint函数永远不会执行,也不会发生错误,当state.account有值时,钩子可以重新尝试启动请求,调用endpoint 函数,这一次你不会出错。

    示例(未测试):

    const useApi = ({endpoint, requestType, body, doRequest = true}) => {
        const [data, setData] = useState({ fetchedData: [], isError: false, isFetchingData: false });
        useEffect(() => {
            if (doRequest) requestApi();
        }, [endpoint, doRequest]); // Retry request when doRequest's value changes
        const requestApi = async () => {
            // invoke endpoint if it is a function
            let endpointUrl = typeof endpoint === 'function' ? endpoint() : endpoint;
            let response = {};
            try {
                setData({ ...data, isFetchingData: true });
                console.log(endpointUrl);
                switch (requestType) {
                    case 'GET':
                        return (response = await axios.get(endpointUrl));
                    case 'POST':
                        return (response = await axios.post(endpointUrl, body));
                    case 'DELETE':
                        return (response = await axios.delete(endpointUrl));
                    case 'UPDATE':
                        return (response = await axios.put(endpointUrl, body));
                    case 'PATCH':
                        return (response = await axios.patch(endpointUrl, body));
                    default:
                        return (response = await axios.get(endpoint));
                }
            } catch (e) {
                console.error(e);
                setData({ ...data, isError: true });
            } finally {
                if (response.data) {
                    setData({ ...data, isFetchingData: false, fetchedData: response.data.mainData });
    
                }
            }
        };
        return data;
    };
    

    用法:

    const Availability = () => {
         [account, setAccount] = useState(0);
         const savedApiData = useAPI({
             endpoint: () => '/programs/${state.account.id}/', // Replace string literal with a factory function
             requestType: 'POST',
             body: {
                siteIds: !state.siteId ? [] : [state.siteId] 
             },
             doRequest: !!state.account, // Only request if account exists
         }); 
    }
    

    【讨论】:

    • 感谢您的回答!我不太明白你关于端点回调的第二个建议你能用一个基本的代码示例详细说明吗?
    • 我刚刚添加了一个例子
    猜你喜欢
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    • 2019-04-14
    • 2020-01-12
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    • 2022-10-12
    相关资源
    最近更新 更多