继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

useRequest学习:新手入门教程

哆啦的时光机
关注TA
已关注
手记 236
粉丝 22
获赞 54
概述

useRequest 是一个用于在 React 应用程序中进行 HTTP 请求的 Hook,结合了 useEffectuseState 的功能,使得请求逻辑和状态管理更加简洁直观。useRequest 通常用于从远程服务器获取数据或向服务器发送数据,实现数据的同步更新。本文将详细介绍 useRequest 的用法、配置选项和常见应用场景。

什么是useRequest

useRequest 是一个用于在 React 应用程序中进行 HTTP 请求的 Hook。它通过将请求逻辑和状态管理集成到组件中,简化了数据的获取和更新流程。与传统的请求方式相比,useRequest 具有以下优势:

  • 代码简洁:请求逻辑直接嵌入到组件中,减少了复杂的状态管理和副作用处理。
  • 响应式更新:当请求的数据发生变化时,组件能够自动更新显示的新数据。
  • 错误处理:方便地捕获和处理请求中的错误。

useRequest 的常见应用场景包括:

  • 获取用户信息、产品列表等数据。
  • 发布评论、点赞等用户行为。
  • 刷新页面中的某些数据。
useRequest的基本用法

使用 useRequest 的基本步骤包括:

  1. 引入库:首先需要引入 useRequest 和相关的库,通常会使用 axios 作为 HTTP 客户端。
  2. 定义请求配置:定义请求的 URL、方法、参数等。
  3. 使用 Hook:利用 useRequest Hook 进行请求。
  4. 处理响应:在请求成功时更新组件状态或执行其他操作。

示例代码

import React, { useState } from 'react';
import axios from 'axios';
import { useRequest } from 'ahooks'; // 引入 ahooks 库中的 useRequest

const MyComponent = () => {
    const [data, setData] = useState(null);

    const { run, loading, error } = useRequest(
        () => axios.get('https://api.example.com/data'), // 定义请求配置
        {
            onSuccess: (data) => { // 请求成功时的回调
                console.log(data);
                setData(data);
            },
            onError: (error) => { // 请求出错时的回调
                console.error(error);
            },
            manual: true // 手动触发请求,默认是 false
        }
    );

    return (
        <div>
            {loading && <div>Loading...</div>}
            {error && <div>Error!</div>}
            {data && <div>Data: {JSON.stringify(data)}</div>}
            <button onClick={run}>Fetch Data</button> // 手动触发请求
        </div>
    );
};

export default MyComponent;
``

### 代码解析

- `useRequest` 接收两个参数,第一个是请求函数,第二个是配置对象。
- `run` 是一个触发请求的函数。
- `loading` 是一个布尔值,表明请求是否正在进行。
- `error` 是一个错误对象,表示请求过程中发生错误。
- `onSuccess` 和 `onError` 分别是请求成功和失败时的回调函数。

## useRequest的配置选项详解

`useRequest` Hook 接收一个配置选项作为第二个参数,这些配置选项可以自定义 Hook 的行为。以下是一些常见的配置选项:

### `manual`

默认值:`false`
- **描述**:如果为 `true`,则请求不会在组件挂载时自动触发,需要手动调用 `run` 函数来触发请求。
- **示例**:
    ```jsx
    const { run, loading, data } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            manual: true
        }
    );

onSuccess

  • 描述:请求成功时执行的回调函数。
  • 示例
    const { run, loading, data } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onSuccess: (data) => {
                console.log('Success:', data);
            }
        }
    );

onError

  • 描述:请求失败时执行的回调函数。
  • 示例
    const { run, loading, error } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onError: (error) => {
                console.error('Error:', error);
            }
        }
    );

onSettled

  • 描述:无论请求成功还是失败都会执行的回调函数。
  • 示例
    const { run, loading, data, error } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onSettled: (data, error) => {
                console.log('Settled:', data, error);
            }
        }
    );

onMount

  • 描述:在组件挂载时自动触发请求。
  • 示例
    const { loading, data, error } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onMount: true
        }
    );

onUpdate

  • 描述:在请求更新时执行的回调函数。
  • 示例
    const { update, loading, data } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onUpdate: (data) => {
                console.log('Update:', data);
            }
        }
    );

dependencies

  • 描述:请求配置的依赖列表。当这些依赖发生变化时,会重新发起请求。
  • 示例
    const { run, loading, data, error } = useRequest(
        (params) => axios.get('https://api.example.com/data', { params }),
        {
            dependencies: ['someKey'],
            onSuccess: (data) => {
                console.log('Success:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
            }
        }
    );

onAbort

  • 描述:请求被取消时执行的回调函数。
  • 示例
    const { abort, loading, data, error } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onAbort: (data) => {
                console.log('Abort:', data);
            }
        }
    );

onTrigger

  • 描述:在请求触发时执行的回调函数。
  • 示例
    const { run, loading, data, error } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onTrigger: (data) => {
                console.log('Trigger:', data);
            }
        }
    );
useRequest的常见应用场景

useRequest 可以用于各种需要与服务器交互的场景,以下是一些常见的应用场景:

获取初始数据

在组件挂载时从服务器获取初始数据:

const MyComponent = () => {
    const { data, loading, error } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onMount: true,
            onSuccess: (data) => {
                console.log('Initial data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error!</div>;

    return <div>Data: {JSON.stringify(data)}</div>;
};

手动触发请求

当用户点击按钮时手动触发请求:

const MyComponent = () => {
    const [trigger, { data, loading, error }] = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            manual: true,
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error).
            { console.error('Error:', error); }
        }
    );
    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error!</div>;

    return (
        <div>
            <button onClick={trigger}>Fetch Data</button>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};

更新数据

依赖于某些变化重新发起请求:

const MyComponent = () => {
    const [key, setKey] = useState('initialKey');
    const { data, loading, error } = useRequest(
        (params) => axios.get('https://api.example.com/data', { params }),
        { dependencies: [key],
            onSuccess: (data) => {
            console.log('Data:', data);
        },
        onError: (error) => {
            console.error('Error:', error);
        }
    });

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error!</div>;

    return (
        <div>
            <div>Data: {JSON.stringify(data)}</div>
            <button onClick={() => setKey('newKey')}>Update Key</button>
        </div>
    );
};

请求取消

在组件卸载时取消请求,避免不必要的请求:

const MyComponent = () => {
    const { run, loading, data, error, abort } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onMount: true,
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
            },
            onUnmount: () => {
                abort();
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error!</div>;

    return (
        <div>
            <div>Data: {JSON.stringify(data)}</div>
        </div>
    );
};

请求重试

请求失败时自动重试:

const MyComponent = () => {
    const { run, loading, data, error, retry } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onMount: true,
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
                retry();
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error!</div>;

    return (
        <div>
            <button onClick={run}>Fetch Data</button>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};
useRequest的错误处理方法

useRequest 提供了多种方式处理请求中的错误情况,以下是一些常见的错误处理方法:

基本错误处理

在请求失败时执行错误处理逻辑:

const MyComponent = () => {
    const { run, loading, error } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onError: (error) => {
                console.error('Error:', error);
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error!</div>;

    return (
        <div>
            <button onClick={run}>Fetch Data</button>
        </div>
    );
};

自定义错误处理

使用自定义的错误处理函数,例如显示错误消息:

const MyComponent = () => {
    const [errorMessage, setErrorMessage] = useState(null);

    const { run, loading, error } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onError: (error) => {
                console.error('Error:', error);
                setErrorMessage(error.message);
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {errorMessage}</div>;

    return (
        <div>
            <button onClick={run}>Fetch Data</button>
        </div>
    );
};

自动重试

请求失败时自动重试,直到请求成功或达到最大重试次数:

const MyComponent = () => {
    const { run, loading, data, error, retry } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onError: (error) => {
                console.error('Error:', error);
                retry();
            },
            retry: { times: 3, interval: 1000 }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <button onClick={run}>Fetch Data</button>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};

请求取消

在某些情况下取消请求,例如页面卸载时:

const MyComponent = () => {
    const { run, loading, data, error, abort } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onMount: true,
            onError: (error) => {
                console.error('Error:', error);
            },
            onUnmount: () => {
                abort();
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <div>Data: {JSON.stringify(data)}</div>
        </div>
    );
};
useRequest的优化技巧

使用缓存

减少不必要的请求,提高应用性能:

const MyComponent = () => {
    const { run, loading, data, error } = useRequest(
        (params) => axios.get('https://api.example.com/data', { params }),
        {
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
            },
            cache: true
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <button onClick={run}>Fetch Data</button>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};

调整请求间隔

控制请求的时间间隔,避免过度请求:

const MyComponent = () => {
    const { run, loading, data, error } = useRequest(
        (params) => axios.get('https://api.example.com/data', { params }),
        {
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
            },
            interval: 3000
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <button onClick={run}>Fetch Data</button>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};

使用错误码处理

根据不同的错误码返回不同的处理逻辑:

const MyComponent = () => {
    const [error, setError] = useState(null);

    const { run, loading, data, error: requestError } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
                setError(error);
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) {
        if (error.response && error.response.status === 401) {
            return <div>Unauthorized</div>;
        }
        if (error.response && error.response.status === 404) {
            return <div>Not Found</div>;
        }
        return <div>Error: {error.message}</div>;
    }

    return (
        <div>
            <button onClick={run}>Fetch Data</button>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};

使用依赖关系

根据依赖关系重新发起请求,避免不必要的请求:

const MyComponent = () => {
    const [key, setKey] = useState('initialKey');
    const { data, loading, error } = useRequest(
        (params) => axios.get('https://api.example.com/data', { params }),
        {
            dependencies: [key],
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <button onClick={() => setKey('newKey')}>Update Key</button>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};

并发请求

同时发起多个请求,并对每个请求的结果进行处理:

const MyComponent = () => {
    const [data1, setData1] = useState(null);
    const [data2, setData2] = useState(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);

    const request1 = useRequest(
        () => axios.get('https://api.example.com/data1'),
        {
            onSuccess: (data) => {
                console.log('Data1:', data);
                setData1(data);
            },
            onError: (error) => {
                console.error('Error1:', error);
                setError(error);
            }
        }
    );

    const request2 = useRequest(
        () => axios.get('https://api.example.com/data2'),
        {
            onSuccess: (data) => {
                console.log('Data2:', data);
                setData2(data);
            },
            onError: (error) => {
                console.error('Error2:', error);
                setError(error);
            }
        }
    );

    React.useEffect(() => {
        setLoading(true);
        request1.run();
        request2.run();
    }, []);

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <div>Data1: {JSON.stringify(data1)}</div>
            <div>Data2: {JSON.stringify(data2)}</div>
        </div>
    );
};

数据缓存和版本控制

使用缓存来减少请求次数,并在必要时更新缓存数据:

const MyComponent = () => {
    const [key, setKey] = useState('initialKey');
    const { data, loading, error } = useRequest(
        (params) => axios.get('https://api.example.com/data', { params }),
        {
            dependencies: [key],
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
            },
            cache: true
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <button onClick={() => setKey('newKey')}>Update Key</button>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};

优化请求参数

根据不同的场景动态调整请求参数:

const MyComponent = () => {
    const [params, setParams] = useState({ key: 'initialKey' });
    const { data, loading, error } = useRequest(
        (params) => axios.get('https://api.example.com/data', { params }),
        {
            dependencies: [params],
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <button onClick={() => setParams({ key: 'newKey' })}>Update Params</button>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};

使用中间件

使用中间件来处理请求前后的逻辑:

const MyComponent = () => {
    const { data, loading, error } = useRequest(
        (params) => axios.get('https://api.example.com/data', { params }),
        {
            onSuccess: (data) => {
                console.log('Data:', data);
            },
            onError: (error) => {
                console.error('Error:', error);
            },
            onBeforeRequest: ({ params }) => {
                console.log('Before request:', params);
                return params;
            },
            onAfterRequest: (data) => {
                console.log('After request:', data);
                return data;
            }
        }
    );

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            {data && <div>Data: {JSON.stringify(data)}</div>}
        </div>
    );
};

持久化状态

在组件卸载后再重新加载时保留请求状态:

const MyComponent = () => {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);

    const { run, loading: requestLoading, error: requestError } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onSuccess: (data) => {
                console.log('Data:', data);
                setData(data);
            },
            onError: (error) => {
                console.error('Error:', error);
                setError(error);
            }
        }
    );

    React.useEffect(() => {
        setLoading(true);
        run();
    }, []);

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <div>Data: {JSON.stringify(data)}</div>
        </div>
    );
};

使用上下文

在组件树中共享请求状态和逻辑:

import React, { useContext, useState } from 'react';
import axios from 'axios';
import { useRequest } from 'ahooks';
import { RequestContext } from './RequestContext';

const MyComponent = () => {
    const { data, loading, error } = useContext(RequestContext);

    if (loading) return <div>Loading...</div>;
    if (error) return <div>Error: {error.message}</div>;

    return (
        <div>
            <div>Data: {JSON.stringify(data)}</div>
        </div>
    );
};

const RequestProvider = ({ children }) => {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);

    const { run, loading: requestLoading, error: requestError } = useRequest(
        () => axios.get('https://api.example.com/data'),
        {
            onSuccess: (data) => {
                console.log('Data:', data);
                setData(data);
            },
            onError: (error) => {
                console.error('Error:', error);
                setError(error);
            }
        }
    );

    React.useEffect(() => {
        setLoading(true);
        run();
    }, []);

    return (
        <RequestContext.Provider value={{ data, loading, error }}>
            {children}
        </RequestContext.Provider>
    );
};

export default RequestProvider;

总结,useRequest 是一个强大且灵活的 Hook,可以用于各种复杂的 HTTP 请求场景。通过合理配置和使用,可以有效提升应用的性能和用户体验。

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP