【问题标题】:How to use a custom React hook to make a POST or DELETE request with Axios如何使用自定义 React 钩子通过 Axios 发出 POST 或 DELETE 请求
【发布时间】:2022-01-22 08:50:19
【问题描述】:

我正在尝试在 React 中创建一个通用的 useAxios 钩子。我希望能够将此钩子导入其他组件以发出 Get、Post 和 Delete 请求。我已经创建了钩子,它可以很好地发出 Get 请求,但我一直在思考如何使它适用于 Post/Delete 请求。

问题是当用户单击保存或删除按钮时我会发出 Post/Delete 请求,但我无法从事件处理函数或 useEffect 调用 React 挂钩。

下面是我创建的通用钩子:

import { useState, useEffect } from "react";
import axios from "axios";

export interface AxiosConfig<D> {
    method?: 'get' | 'post' | 'delete' | 'put';
    url: string;
    data?: D;
    params?: URLSearchParams;
}

export const useAxios = <T, D = undefined >(config: AxiosConfig<D>) => {
    
    const [responseData, setResponseData] = useState<T>();
    const [isLoading, setIsloading] = useState(true);
    const [isError, setIsError] = useState(false);

    useEffect(() => {
        const controller = new AbortController();
        const axiosRequest = async () => {
            try {
                const response = await axios({ ...config, signal: controller.signal })
                setResponseData(response.data)
                setIsloading(false);
            } catch (error) {

                setIsError(true);
                setIsloading(false);
            }
        }

        axiosRequest();

        return () => {
            controller.abort();
        }
    }, [config.url, config.method, config.data, config.params])

    return {responseData, isLoading, isError}
}

这是我想发出删除请求的组件示例

import { useParams } from 'react-router';
import { useAxios } from '../../api/hooks/useAxios';

export interface IItem {
    title: string;
    info: string;
}

export default function Item() {
    const { id } = useParams<{id?: string}>();

    const {responseData: item, isLoading, isError} = useAxios<IItem>({
        method: 'get',
        url: `http://localhost:3000/items/${id}`
    })

    const handleDelete = () => {
        //not sure what to do here. Need to make DELETE request

    }

    return (
        <div>
            {isLoading && <p className='loading'>Loading...</p>}
            {isError && <p className='error'>Could Not Load Item</p>}
            {item && (
                <>
                    <h2>{item.title}</h2>
                    <p>{item.info}</p>
                    <button onClick={handleDelete}>Delete</button>
                </>
            )}
        </div>
    )
}

我可以直接在 Item 组件中发出 axios 请求,而不使用我的 useAxios 挂钩,但我最终会在整个应用程序中重复代码。

【问题讨论】:

  • 您正在尝试减少冗余,但我不建议您在整个组件中插入 API 请求,因为这会导致冗余较少但 API 紧张的组件。您最好使用推荐的方法在商店级别处理您的请求,并且可能有一个通用的操作创建器。

标签: javascript reactjs typescript react-hooks axios


【解决方案1】:

假设您的 DELETE 路由与 GET 路由相同,您只需将方法类型存储在本地状态变量中并进行更改:

const { id } = useParams<{id?: string}>();
const [method, setMethod] = useState('get');

const {responseData: item, isLoading, isError} = useAxios<IItem>({
  method,
  url: `http://localhost:3000/items/${id}`
});

const handleDelete = () => setMethod('delete');

但是,我想您会意识到这只能解决部分问题,即您将组件的返回 JSX 与 GET 请求 (IItem) 的响应类型紧密耦合。

【讨论】:

  • 谢谢您,这确实可以删除该项目!将组件的 JSX 耦合到 API 响应是否被认为是不好的做法?将 API 调用 eslewhere 并将结果作为 props 传递给组件会更好吗?
  • 如果组件在没有获取数据的情况下无法真正发挥作用,那么向上获取并作为 props 传递更为惯用。
猜你喜欢
  • 2018-04-25
  • 1970-01-01
  • 1970-01-01
  • 2019-10-26
  • 2020-09-21
  • 2020-11-07
  • 2022-11-02
  • 2021-03-01
  • 2021-06-08
相关资源
最近更新 更多