useRequest学习:新手入门教程
useRequest
是一个用于在 React 应用程序中进行 HTTP 请求的 Hook,结合了 useEffect
和 useState
的功能,使得请求逻辑和状态管理更加简洁直观。useRequest
通常用于从远程服务器获取数据或向服务器发送数据,实现数据的同步更新。本文将详细介绍 useRequest
的用法、配置选项和常见应用场景。
useRequest
是一个用于在 React 应用程序中进行 HTTP 请求的 Hook。它通过将请求逻辑和状态管理集成到组件中,简化了数据的获取和更新流程。与传统的请求方式相比,useRequest
具有以下优势:
- 代码简洁:请求逻辑直接嵌入到组件中,减少了复杂的状态管理和副作用处理。
- 响应式更新:当请求的数据发生变化时,组件能够自动更新显示的新数据。
- 错误处理:方便地捕获和处理请求中的错误。
useRequest
的常见应用场景包括:
- 获取用户信息、产品列表等数据。
- 发布评论、点赞等用户行为。
- 刷新页面中的某些数据。
使用 useRequest
的基本步骤包括:
- 引入库:首先需要引入
useRequest
和相关的库,通常会使用axios
作为 HTTP 客户端。 - 定义请求配置:定义请求的 URL、方法、参数等。
- 使用 Hook:利用
useRequest
Hook 进行请求。 - 处理响应:在请求成功时更新组件状态或执行其他操作。
示例代码
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
可以用于各种需要与服务器交互的场景,以下是一些常见的应用场景:
获取初始数据
在组件挂载时从服务器获取初始数据:
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 请求场景。通过合理配置和使用,可以有效提升应用的性能和用户体验。
共同学习,写下你的评论
评论加载中...
作者其他优质文章