![](/img/trans.png)
[英]How to return the result of " axios' POST request " from reducer function in react
[英]How to cancel a dispatched axios request from reducer
我在我的组件中使用了 useEffects 来加载数据,组件安装的那一刻。 但我正在尝试通过避免任何内存泄漏来优化我的代码。 为实现这一点,如果组件卸载,我将尝试使用 AbortController 在任何情况下取消任何请求。 像这样的东西
useEffect(() => {
let abortController;
(async () {
abortController = new AbortController();
let signal = abortController.signal;
// the signal is passed into the request(s) we want to abort using this controller
const { data } = await axios.get(
'https://random-data-api.com/api/company/random_company',
{ signal: signal }
);
setCompany(data);
})();
return () => abortController.abort();
}, []);
但我发现很难实现这一点,因为我的 axios 请求位于服务文件中,该文件由切片文件中的缩减器调用。 下面是我的组件的 useEffect。
// Component.js
import { bookDetails } from '../../features/user/userSlice'
//import reducer from my slice file
.
.
// code
useEffect(() => {
let mounted = true
if (mounted) {
dispatch(bookDetails(bookId))
}
return () => mounted = false
}, [])
下面是我的切片文件中的减速器,它从我的服务文件中导入 function。
// userSlice.js
import userService from "./userService";
export const bookDetails = createAsyncThunk(
"user/book",
async (id, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.user.token;
return await userService.bookDetails({ id, token });
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
);
下面是我的服务文件中的 function
// userService.js
const bookDetails = async ({ id, token }) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
};
const response = await axios.get(API_URL + `/book/${id}`, config);
return response.data;
};
我想取消此请求,以防我的组件从 useEffect 卸载。 请帮忙。 提前致谢。
由于您使用的是 Redux Toolkit 的 createAsyncThunk,因此听起来您正在寻找 createAsyncThunk 的“运行时取消”功能。 也许像下面这样:
export const bookDetails = createAsyncThunk(
"user/book",
async (id, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.user.token;
return await userService.bookDetails({ id, token, signal: thunkAPI.signal });
} catch (error) {
return thunkAPI.rejectWithValue(getErrorMessage(error));
}
}
);
useEffect(() => {
const promise = dispatch(bookDetails(bookId));
return () => promise.abort();
}, [])
但是,如果您担心的只是获取数据,我强烈建议您查看RTK Query 、 React Query或SWR 。 这些处理异步获取数据的常见模式,无需您自己编写各种切片和缩减程序,并添加有用的功能,如缓存、重试等。
让您的bookDetails
方法接受一个名为signal
的额外属性。 然后将其传递给axios
方法。
const bookDetails = async ({ id, token, signal }) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
signal,
};
const response = await axios.get(API_URL + `/book/${id}`, config);
return response.data;
};
为此,像这样更改您的 reducer 方法:
async ({ id, signal}, thunkAPI) => {
try {
const token = thunkAPI.getState().auth.user.token;
return await userService.bookDetails({ id, token, signal });
} catch (error) {
const message =
(error.response &&
error.response.data &&
error.response.data.message) ||
error.message ||
error.toString();
return thunkAPI.rejectWithValue(message);
}
}
最后派发这样的动作:
abortController = new AbortController();
let signal = abortController.signal;
dispatch(bookDetails({ id: bookId, signal: signal ))
最好有一个AbortController
来避免在使用useEffect
加载数据时发生 memory 泄漏 当在调度请求期间可能出错时这将很有用,以避免在发生错误时请求仍在运行,这是一个示例,您可以使用它来取消请求 state 是否因任何原因未加载。
import { useEffect, useState } from 'react';
const MyComponent = () => {
const [data, setData] = useState(null); // set state to null
useEffect(() => {
const controller = new AbortController(); // AbortController instance
// Dispatch the request
fetch('/data', { signal: controller.signal })
.then(response => response.json()) // get response
.then(data => setData(data)) // Updating useState
.catch(e => { // Catch errors
if (e.name === 'AbortError') {
console.log("Failed to fetching data");
}
throw e;
});
// cleanup controller
return () => {
controller.abort();
};
}, []);
// Render the component
return <div>{data && data.message}</div>;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.