基础使用
这一小节我们会介绍 useRequest
最核心,最基础的能力,也就是 useRequest
内核的能力。
默认请求
默认情况下,useRequest
第一个参数是一个异步函数,在组件初始化时,会自动执行该异步函数。同时自动管理该异步函数的 loading
, data
, error
等状态。
- React
- Vue
const { data, error, loading } = useRequest(getUsername);
<template>
<block>
<view>{{request.loading}}</view>
<view>{{request.data}}</view>
<view>{{request.error}}</view>
</block>
</template>
<script>
export default {
setup() {
// 由于要保证request内部的变量不失活。 这里简单的可以将request直接抛出
const request = useRequest(getUsername);
return {
request,
};
},
};
</script>
- React
- Vue
import React from 'react';
import { View } from '@tarojs/components';
import DemoContent from '@src/components/DemoContent';
import { useRequest } from 'taro-hooks';
import Mock from 'mockjs';
function getUsername(): Promise<string> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve(Mock.mock('@name()'));
} else {
reject(new Error('Failed to get username'));
}
}, 1000);
});
}
export default () => {
const { data, error, loading } = useRequest(getUsername);
return (
<DemoContent title="Basic - 默认用法" desc="读取用户名称">
{error ? (
<View>{error.message}</View>
) : loading ? (
<View>loading...</View>
) : (
<View>Username: {data}</View>
)}
</DemoContent>
);
};
<template>
<block>
<demo-content title="Basic - 默认用法" desc="读取用户名称">
<view v-if="request.loading"> loading... </view>
<template v-else>
<view v-if="request.error"> error: {{ request.error.message }} </view>
<view v-else> Username: {{ request.data }} </view>
</template>
</demo-content>
</block>
</template>
<script>
import { useRequest } from 'taro-hooks';
import Mock from 'mockjs';
function getUsername() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve(Mock.mock('@name()'));
} else {
reject(new Error('Failed to get username'));
}
}, 1000);
});
}
export default {
setup() {
const request = useRequest(getUsername);
return { request };
},
};
</script>
手动触发
如果设置了 options.manual = true
,则 useRequest
不会默认执行,需要通过 run
或者 runAsync
来触发执行。
- React
- Vue
const { loading, run, runAsync } = useRequest(service, {
manual: true,
});
<button onClick={run} disabled={loading}>
{loading ? 'Loading' : 'Edit'}
</button>;
<template>
<block>
<button @click="request.run()">
{{request.loading ? 'Loading' : 'Edit'}}
</button>
</block>
</template>
<script>
export default {
setup() {
// 由于要保证request内部的变量不失活。 这里简单的可以将request直接抛出
const request = useRequest(service, {
manual: true,
});
return {
request,
};
},
};
</script>
run
与 runAsync
的区别在于:
run
是一个普通的同步函数,我们会自动捕获异常,你可以通过options.onError
来处理异常时的行为。runAsync
是一个返回Promise
的异步函数,如果使用runAsync
来调用,则意味着你需要自己捕获异常。runAsync()
.then((data) => {
console.log(data);
})
.catch((error) => {
console.log(error);
});
接下来我们通过修改用户名这个简单的场景,来演示 useRequest 手动触发模式,以及 run
与 runAsync
的区别。
- React
- Vue
import React from 'react';
import DemoContent from '@src/components/DemoContent';
import { Button, Input, Field } from '@taroify/core';
import { showToast } from '@tarojs/taro';
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
function editUsername(username: string): Promise<void> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default () => {
const [state, setState] = useState('');
const { loading, run } = useRequest(editUsername, {
manual: true,
onSuccess: (result, params) => {
setState('');
showToast({
title: 'The username was changed to "${params[0]}" !',
icon: 'success',
});
},
onError: (error) => {
showToast({ title: error.message, icon: 'error' });
},
});
return (
<DemoContent
title="Basic - 手动触发"
desc="在这个例子中,我们通过 run(username) 来修改用户名,通过 onSuccess 和 onError 来处理成功和失败"
>
<Field align="center">
<Input
onChange={(e) => setState(e.detail.value)}
value={state}
placeholder="Please enter username"
/>
<Button
disabled={loading}
loading={loading}
color="primary"
size="small"
onClick={() => run(state)}
>
{loading ? 'Loading' : 'Edit'}
</Button>
</Field>
</DemoContent>
);
};
<template>
<block>
<demo-content
title="Basic - 手动触发"
desc="在这个例子中,我们通过 run(username) 来修改用户名,通过 onSuccess 和 onError 来处理成功和失败"
>
<nut-input
:disabled="request.loading"
v-model="state"
placeholder="Please enter username"
>
<template #button>
<nut-button
:loading="request.loading"
size="small"
type="primary"
shape="square"
@click="request.run(state)"
>{{ request.loading ? 'Loading' : 'Edit' }}</nut-button
>
</template>
</nut-input>
</demo-content>
</block>
</template>
<script>
import { showToast } from '@tarojs/taro';
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
function editUsername() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default {
setup() {
const [state, setState] = useState('');
const request = useRequest(editUsername, {
manual: true,
onSuccess: (result, params) => {
setState('');
showToast({
title: 'The username was changed to "${params[0]}" !',
icon: 'success',
});
},
onError: (error) => {
showToast({ title: error.message, icon: 'error' });
},
});
return {
request,
state,
};
},
};
</script>
- React
- Vue
import React from 'react';
import DemoContent from '@src/components/DemoContent';
import { Button, Input, Field } from '@taroify/core';
import { showToast } from '@tarojs/taro';
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
function editUsername(username: string): Promise<void> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default () => {
const [state, setState] = useState('');
const { loading, runAsync } = useRequest(editUsername, {
manual: true,
});
const onClick = async () => {
try {
await runAsync(state);
setState('');
showToast({
title: 'The username was changed to "${state}" !',
icon: 'success',
});
} catch (error) {
showToast({ title: error.message, icon: 'error' });
}
};
return (
<DemoContent
title="Basic - 手动触发"
desc="在这个例子中,我们通过 runAsync(username) 来修改用户名,此时必须通过 catch 来自行处理异常。"
>
<Field align="center">
<Input
onChange={(e) => setState(e.detail.value)}
value={state}
placeholder="Please enter username"
/>
<Button
disabled={loading}
loading={loading}
color="primary"
size="small"
onClick={onClick}
>
{loading ? 'Loading' : 'Edit'}
</Button>
</Field>
</DemoContent>
);
};
<template>
<block>
<demo-content
title="Basic - 手动触发"
desc="在这个例子中,我们通过 runAsync(username) 来修改用户名,此时必须通过 catch 来自行处理异常。"
>
<nut-input
:disabled="request.loading"
v-model="state"
placeholder="Please enter username"
>
<template #button>
<nut-button
:loading="request.loading"
size="small"
type="primary"
shape="square"
@click="handleRunAsync()"
>{{ request.loading ? 'Loading' : 'Edit' }}</nut-button
>
</template>
</nut-input>
</demo-content>
</block>
</template>
<script>
import { showToast } from '@tarojs/taro';
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
import { escapeState } from '@taro-hooks/shared';
function editUsername() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default {
setup() {
const [state, setState] = useState('');
const request = useRequest(editUsername, {
manual: true,
});
const handleRunAsync = async () => {
const { runAsync } = escapeState(request);
const username = escapeState(state);
try {
await runAsync(username);
setState('');
showToast({
title: 'The username was changed to "${username}" !',
icon: 'success',
});
} catch (error) {
showToast({ title: error.message, icon: 'error' });
}
};
return {
request,
state,
handleRunAsync,
};
},
};
</script>
生命周期
useRequest
提供了以下几个生命周期配置项,供你在异步函数的不同阶段做一些处理。
onBefore
:请求之前触发onSuccess
:请求成功触发onError
:请求失败触发onFinally
:请求完成触发
- React
- Vue
import React from 'react';
import DemoContent from '@src/components/DemoContent';
import { Button, Input, Field, Progress } from '@taroify/core';
import { showToast } from '@tarojs/taro';
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
function editUsername(username: string): Promise<void> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default () => {
const [state, setState] = useState<string>('');
const [progress, setProgress] = useState<number>(0);
const [status, setStatus] = useState<string | undefined>();
// edit username
const { loading, run } = useRequest(editUsername, {
manual: true,
onBefore: (params) => {
setProgress(0);
// @ts-ignore
setStatus();
showToast({
icon: 'none',
title: 'Start Request: ${params[0]}',
});
},
onSuccess: (result, params) => {
setState('');
setStatus('heart-fill');
showToast({
icon: 'success',
title: 'The username was changed to "${params[0]}" !',
});
},
onError: (error) => {
setStatus('del2');
showToast({
icon: 'error',
title: error.message,
});
},
onFinally: (params, result, error) => {
setProgress(100);
},
});
return (
<DemoContent title="Basic - 生命周期">
<Field align="center">
<Input
onChange={(e) => setState(e.detail.value)}
value={state}
placeholder="Please enter username"
/>
<Button
disabled={loading}
loading={loading}
color="primary"
size="small"
onClick={() => run(state)}
>
{loading ? 'Loading' : 'Edit'}
</Button>
</Field>
<Progress percent={progress} />
</DemoContent>
);
};
<template>
<block>
<demo-content title="Basic - 生命周期">
<nut-input
:disabled="request.loading"
v-model="state"
placeholder="Please enter username"
>
<template #button>
<nut-button
:loading="request.loading"
size="small"
type="primary"
shape="square"
@click="request.run(state)"
>{{ request.loading ? 'Loading' : 'Edit' }}</nut-button
>
</template>
</nut-input>
<nut-progress
:percentage="progress"
:text-inside="!status?.length"
:status="status?.length ? 'icon' : 'text'"
:icon-name="status"
icon-color="#a773ed"
></nut-progress>
</demo-content>
</block>
</template>
<script>
import { showToast } from '@tarojs/taro';
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
function editUsername(username) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default {
setup() {
const [state, setState] = useState('');
const [progress, setProgress] = useState(0);
const [status, setStatus] = useState();
const request = useRequest(editUsername, {
manual: true,
onBefore: (params) => {
setProgress(0);
setStatus();
showToast({
icon: 'none',
title: 'Start Request: ${params[0]}',
});
},
onSuccess: (result, params) => {
setState('');
setStatus('heart-fill');
showToast({
icon: 'success',
title: 'The username was changed to "${params[0]}" !',
});
},
onError: (error) => {
setStatus('del2');
showToast({
icon: 'error',
title: error.message,
});
},
onFinally: (params, result, error) => {
setProgress(100);
},
});
return { request, state, progress, status };
},
};
</script>
刷新(重复上一次请求)
useRequest
提供了 refresh
和 refreshAsync
方法,使我们可以使用上一次的参数,重新发起请求。
假如在读取用户信息的场景中
- 我们读取了 ID 为 1 的用户信息
run(1)
- 我们通过某种手段更新了用户信息
- 我们想重新发起上一次的请求,那我们就可以使用
refresh
来代替run(1)
,这在复杂参数的场景中是非常有用的
- React
- Vue
import React from 'react';
import { View } from '@tarojs/components';
import DemoContent from '@src/components/DemoContent';
import { Button } from '@taroify/core';
import { useEffect } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
import Mock from 'mockjs';
function getUsername(id: number): Promise<string> {
console.log('use-request-refresh-id', id);
return new Promise((resolve) => {
setTimeout(() => {
resolve(Mock.mock('@name()'));
}, 1000);
});
}
export default () => {
const { data, loading, run, refresh } = useRequest(
(id: number) => getUsername(id),
{
manual: true,
},
);
useEffect(() => {
run(1);
}, []);
return (
<DemoContent title="Basic - 刷新(重复上一次请求)" desc="刷新用户名称">
{loading ? (
<View>Loading...</View>
) : (
<>
<View>Username: {data}</View>
<Button
disabled={loading}
loading={loading}
color="primary"
size="small"
onClick={refresh}
>
{loading ? 'Loading' : 'Refresh'}
</Button>
</>
)}
</DemoContent>
);
};
<template>
<block>
<demo-content title="Basic - 刷新(重复上一次请求)" desc="刷新用户名称">
<view v-if="request.loading"> loading... </view>
<template v-else>
<view v-if="request.error"> error: {{ request.error.message }} </view>
<view v-else> Username: {{ request.data }} </view>
</template>
<nut-button
:loading="request.loading"
size="small"
type="primary"
shape="square"
@click="request.refresh()"
>{{ request.loading ? 'Loading' : 'Refresh' }}</nut-button
>
</demo-content>
</block>
</template>
<script>
import { useEffect } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
import { escapeState } from '@taro-hooks/shared';
import Mock from 'mockjs';
function getUsername(id) {
console.log('use-request-refresh-id', id);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(Mock.mock('@name()'));
}, 1000);
});
}
export default {
setup() {
const request = useRequest((id) => getUsername(id), {
manual: true,
});
useEffect(() => {
escapeState(request).run(1);
}, []);
return { request };
},
};
</script>
当然 refresh
和 refreshAsync
的区别和 run
和 runAsync
是一致的。
立即变更数据
useRequest
提供了 mutate
, 支持立即修改 useRequest
返回的 data
参数。
mutate
的用法与 React.setState
一致,支持 mutate(newData)
和 mutate((oldData) => newData)
两种写法。
下面的示例,我们演示了一种 mutate
的应用场景。
我们修改了用户名,但是我们不希望等编辑接口调用成功之后,才给用户反馈。而是直接修改页面数据,同时在背后去调用修改接口,等修改接口返回之后,另外提供反馈。
- React
- Vue
import React from 'react';
import { View } from '@tarojs/components';
import DemoContent from '@src/components/DemoContent';
import { Button, Input, Field } from '@taroify/core';
import { showToast } from '@tarojs/taro';
import { useRef, useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
import Mock from 'mockjs';
function getUsername(): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(Mock.mock('@name()'));
}, 1000);
});
}
function editUsername(username: string): Promise<void> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default () => {
// store last username
const lastRef = useRef<string>();
const [state, setState] = useState('');
// get username
const { data: username, mutate } = useRequest(getUsername);
// edit username
const { run: edit, loading } = useRequest(editUsername, {
manual: true,
onSuccess: (result, params) => {
setState('');
showToast({
title: 'The username was changed to "${params[0]}" !',
icon: 'success',
});
},
onError: (error) => {
showToast({ title: error.message, icon: 'error' });
mutate(lastRef.current);
},
});
const onChange = () => {
lastRef.current = username;
mutate(state);
edit(state);
};
return (
<DemoContent title="Basic - 立即变更数据" desc="修改用户名称">
<View>Username: {username}</View>
<Field align="center">
<Input
onChange={(e) => setState(e.detail.value)}
value={state}
placeholder="Please enter username"
/>
<Button
disabled={loading}
loading={loading}
color="primary"
size="small"
onClick={onChange}
>
{loading ? 'Loading' : 'Edit'}
</Button>
</Field>
</DemoContent>
);
};
<template>
<block>
<demo-content title="Basic - 立即变更数据" desc="修改用户名称">
<view>Username: {{ getUserNameRequest.data }}</view>
<nut-input
:disabled="editUserNameRequest.loading"
v-model="state"
placeholder="Please enter username"
>
<template #button>
<nut-button
:loading="editUserNameRequest.loading"
size="small"
type="primary"
shape="square"
@click="onChange()"
>{{ editUserNameRequest.loading ? 'Loading' : 'Edit' }}</nut-button
>
</template>
</nut-input>
</demo-content>
</block>
</template>
<script>
import { showToast } from '@tarojs/taro';
import { useRef, useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
import { escapeState } from '@taro-hooks/shared';
import Mock from 'mockjs';
function getUsername(id) {
console.log('use-request-refresh-id', id);
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(Mock.mock('@name()'));
}, 1000);
});
}
function editUsername() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default {
setup() {
// store last username
const lastRef = useRef();
const [state, setState] = useState('');
// get username
const getUserNameRequest = useRequest(getUsername);
// edit username
const editUserNameRequest = useRequest(editUsername, {
manual: true,
onSuccess: (result, params) => {
setState('');
showToast({
icon: 'success',
title: 'The username was changed to "${params[0]}" !',
});
},
onError: (error) => {
showToast({
icon: 'error',
title: error.message,
});
const { mutate } = escapeState(getUserNameRequest);
mutate(lastRef.current);
},
});
const onChange = () => {
const { data, mutate } = escapeState(getUserNameRequest);
const { run } = escapeState(editUserNameRequest);
const username = escapeState(state);
lastRef.current = data;
mutate(username);
run(username);
};
return { getUserNameRequest, editUserNameRequest, state, onChange };
},
};
</script>
取消请求
useRequest
提供了 cancel
函数,可以取消当前正在进行的请求。同时 useRequest
会在以下时机自动取消当前请求:
- 组件卸载时,取消正在进行的请求
- 竞态取消,当上一次请求还没返回时,又发起了下一次请求,则会取消上一次请求
- React
- Vue
import React from 'react';
import DemoContent from '@src/components/DemoContent';
import { Button, Input, Field, Flex } from '@taroify/core';
import { showToast } from '@tarojs/taro';
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
function editUsername(username: string): Promise<void> {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default () => {
const [state, setState] = useState('');
const { loading, run, cancel } = useRequest(editUsername, {
manual: true,
onSuccess: (result, params) => {
setState('');
showToast({
title: 'The username was changed to "${params[0]}" !',
icon: 'success',
});
},
onError: (error) => {
showToast({ title: error.message, icon: 'error' });
},
});
return (
<DemoContent title="Basic - 取消请求">
<Field align="center">
<Input
onChange={(e) => setState(e.detail.value)}
value={state}
placeholder="Please enter username"
/>
</Field>
<Flex gutter={10}>
<Flex.Item span={12}>
<Button
disabled={loading}
loading={loading}
color="primary"
size="small"
block
onClick={() => run(state)}
>
{loading ? 'Loading' : 'Edit'}
</Button>
</Flex.Item>
<Flex.Item span={12}>
<Button block color="danger" size="small" onClick={() => cancel()}>
Cancel
</Button>
</Flex.Item>
</Flex>
</DemoContent>
);
};
<template>
<block>
<demo-content title="Basic - 取消请求">
<nut-input
:disabled="request.loading"
v-model="state"
placeholder="Please enter username"
>
</nut-input>
<nut-row :gutter="10">
<nut-col :span="12">
<nut-button
:loading="request.loading"
:block="true"
size="small"
type="primary"
shape="square"
@click="request.run(state)"
>
{{ request.loading ? 'Loading' : 'Edit' }}
</nut-button>
</nut-col>
<nut-col :span="12">
<nut-button
size="small"
type="danger"
shape="square"
block
@click="request.cancel()"
>Cancel</nut-button
>
</nut-col>
</nut-row>
</demo-content>
</block>
</template>
<script>
import { showToast } from '@tarojs/taro';
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
function editUsername() {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.5) {
resolve();
} else {
reject(new Error('Failed to modify username'));
}
}, 1000);
});
}
export default {
setup() {
const [state, setState] = useState('');
const request = useRequest(editUsername, {
manual: true,
onSuccess: (result, params) => {
setState('');
showToast({
title: 'The username was changed to "${params[0]}" !',
icon: 'success',
});
},
onError: (error) => {
showToast({ title: error.message, icon: 'error' });
},
});
return {
request,
state,
};
},
};
</script>
参数管理
useRequest
返回的 params
会记录当次调用 service
的参数数组。比如你触发了 run(1, 2, 3)
,则 params
等于 [1, 2, 3]
。
如果我们设置了 options.manual = false
,则首次调用 service
的参数可以通过 options.defaultParams
来设置。
- React
- Vue
import React from 'react';
import { View } from '@tarojs/components';
import DemoContent from '@src/components/DemoContent';
import { Button, Input, Field } from '@taroify/core';
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
import Mock from 'mockjs';
function getUsername(): Promise<string> {
return new Promise((resolve) => {
setTimeout(() => {
resolve(Mock.mock('@name()'));
}, 1000);
});
}
export default () => {
const [state, setState] = useState('');
// get username
const {
data: username,
run,
params,
loading,
} = useRequest(getUsername, {
defaultParams: ['1'],
});
const onChange = () => {
run(state);
};
return (
<DemoContent title="Basic - 参数管理">
<Field align="center">
<Input
onChange={(e) => setState(e.detail.value)}
value={state}
placeholder="Please enter userId"
/>
<Button
disabled={loading}
loading={loading}
color="primary"
size="small"
onClick={onChange}
>
{loading ? 'Loading' : 'Edit'}
</Button>
</Field>
<View>UserId: {params?.[0]}</View>
<View>Username: {username}</View>
</DemoContent>
);
};
<template>
<block>
<demo-content title="Basic - 参数管理">
<nut-input
:disabled="request.loading"
v-model="state"
placeholder="Please enter userId"
>
<template #button>
<nut-button
:loading="request.loading"
size="small"
type="primary"
shape="square"
@click="request.run(state)"
>{{ request.loading ? 'Loading' : 'GetUserName' }}</nut-button
>
</template>
</nut-input>
<view>UserId: {{ request.params[0] }}</view>
<view>UserName: {{ request.data }}</view>
</demo-content>
</block>
</template>
<script>
import { useState } from '@taro-hooks/core';
import { useRequest } from 'taro-hooks';
import Mock from 'mockjs';
function getUsername(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(Mock.mock('@name()'));
}, 1000);
});
}
export default {
setup() {
const [state] = useState('');
const request = useRequest(getUsername, {
defaultParams: ['1'],
});
return {
request,
state,
};
},
};
</script>
API
Vue中不推荐解构再导出. 或者可以自行toRefs. 不然会导致失去响应. (因为request在Vue中是一个Ref)
const {
loading: boolean,
data?: TData,
error?: Error,
params: TParams || [],
run: (...params: TParams) => void,
runAsync: (...params: TParams) => Promise<TData>,
refresh: () => void,
refreshAsync: () => Promise<TData>,
mutate: (data?: TData | ((oldData?: TData) => (TData | undefined))) => void,
cancel: () => void,
} = useRequest<TData, TParams>(
service: (...args: TParams) => Promise<TData>,
{
manual?: boolean,
defaultParams?: TParams,
onBefore?: (params: TParams) => void,
onSuccess?: (data: TData, params: TParams) => void,
onError?: (e: Error, params: TParams) => void,
onFinally?: (params: TParams, data?: TData, e?: Error) => void,
}
);
Result
参数 | 说明 | 类型 |
---|---|---|
data | service 返回的数据 | TData | undefined |
error | service 抛出的异常 | Error | undefined |
loading | service 是否正在执行 | boolean |
params | 当次执行的 service 的参数数组。比如你触发了 run(1, 2, 3) ,则 params 等于 [1, 2, 3] | TParams | [] |
run |
| (...params: TParams) => void |
runAsync | 与 run 用法一致,但返回的是 Promise,需要自行处理异常。 | (...params: TParams) => Promise<TData> |
refresh | 使用上一次的 params,重新调用 run | () => void |
refreshAsync | 使用上一次的 params,重新调用 runAsync | () => Promise<TData> |
mutate | 直接修改 data | (data?: TData / ((oldData?: TData) => (TData / undefined))) => void |
cancel | 取消当前正在进行的请求 | () => void |
Options
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
manual |
| boolean | false |
defaultParams | 首次默认执行时,传递给 service 的参数 | TParams | - |
onBefore | service 执行前触发 | (params: TParams) => void | - |
onSuccess | service resolve 时触发 | (data: TData, params: TParams) => void | - |
onError | service reject 时触发 | (e: Error, params: TParams) => void | - |
onFinally | service 执行完成时触发 | (params: TParams, data?: TData, e?: Error) => void | - |
以上我们介绍了 useRequest 最基础的功能,接下来我们介绍一些更高级的能力。