[英]I get Error: Can't perform a React state update on an unmounted component even though i created cleanup
An error keeps bothering me on my app says一个错误一直困扰着我的应用程序说
Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
I do declare a useEffect in my Context so that I can have a realtime data storing and getting for my app.我确实在我的上下文中声明了一个 useEffect,以便我可以为我的应用程序存储和获取实时数据。
Here is my code in Context;这是我在上下文中的代码;
const FetchProvider = ({ children }) => {
const [userList, setUserList] = useState([]);
const [teamList, setTeamList] = useState([]);
const authContext = useContext(AuthContext);
const authAxios = axios.create({
baseURL: process.env.REACT_APP_API_URL,
});
useEffect(() => {
let isCancelled = false;
if (
authContext.isAuthenticated &&
authContext.authState.userInfo !== null
) {
const getUsers = async () => {
try {
const users = await authAxios.get('/admin/get-all-users');
if (!isCancelled) {
setUserList(users.data);
}
} catch (error) {
if (!isCancelled) {
console.log(error);
}
}
};
const getTeams = async () => {
try {
const teams = await authAxios.get('/get-all-teams');
if (!isCancelled) {
setTeamList(teams.data);
}
} catch (error) {
if (!isCancelled) {
console.log(error);
}
}
};
getUsers();
getTeams();
}
return () => {
isCancelled = true;
};
}, [authAxios, authContext]);
return (
<Provider
value={{
authAxios,
userList,
setUserList,
teamList,
setTeamList,
}}
>
{children}
</Provider>
);
};
And I get this error in my Login.jsx and in my even though I don't declare useEffect in submitting and declaring it in.我在我的 Login.jsx 和我的 Login.jsx 中得到了这个错误,即使我在提交和声明它时没有声明 useEffect 。
Here is my code;这是我的代码;
const submitCredentials = async (credentials, resetForm) => {
try {
setLoginLoading(true);
const { data } = await publicFetch.post('signin', credentials);
authContext.setAuthState(data);
setSignupSuccess(data.message);
setSignupError('');
setOpen(true);
setTimeout(() => {
setLoginLoading(false);
setredirectOnlogin(true);
resetForm(true);
}, 400);
} catch (error) {
setLoginLoading(false);
const { data } = error.response;
setSignupError(data.message);
setSignupSuccess('');
setOpen(true);
}
return setLoginLoading(false);
};
And I have tried many ways the internet has offered to fix this up but unfortunately it does not fix my problem.我已经尝试了互联网提供的许多方法来解决这个问题,但不幸的是它并没有解决我的问题。
I do have useEffect in my UsersTable.jsx and TeamTables.jsx.我的 UsersTable.jsx 和 TeamTables.jsx 中确实有 useEffect。
Here is my code in UsersTable.jsx;这是我在 UsersTable.jsx 中的代码;
useEffect(() => {
let isCancelled = false;
const getUsers = async () => {
try {
const users = await fetchContext.authAxios.get('/admin/get-all-users');
setIsLoaded(true);
if (isLoaded === true) {
if (!isCancelled) {
fetchContext.setUserList(users.data);
}
}
return () => {
isCancelled = true;
};
} catch (error) {
if (!isCancelled) {
console.log(error);
}
}
};
getUsers();
return () => {
isCancelled = true;
};
}, [fetchContext, isLoaded]);
Here is my useEffect code in my TeamTable.jsx;这是我的 TeamTable.jsx 中的 useEffect 代码;
useEffect(() => {
let isCancelled = false;
const getTeams = async () => {
try {
const teams = await fetchContext.authAxios.get('get-all-teams');
setIsLoaded(true);
if (isLoaded === true) {
if (!isCancelled) {
fetchContext.setTeamList(teams.data);
}
}
} catch (error) {
if (!isCancelled) {
console.log(error);
}
}
};
getTeams();
return () => {
isCancelled = true;
};
}, [fetchContext, isLoaded]);
The isLoaded is used as an AJAX isLoaded 用作 AJAX
Well, you can use the React recommended way to fix this issue.好吧,你可以使用 React 推荐的方法来解决这个问题。 All you need to do is wrap your api call within makeCancellable method and cancel them when your component is unmounting.
您需要做的就是将 api 调用包装在 makeCancellable 方法中,并在卸载组件时取消它们。
Ref: https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html参考: https://reactjs.org/blog/2015/12/16/ismounted-antipattern.html
To do that create为此创建
const makeCancelable = (promise) => {
let isCancelled = false;
const wrappedPromise = new Promise((resolve, reject) => {
promise.then(
val => isCancelled ? reject({isCanceled: true}) : resolve(val),
error => isCancelled ? reject({isCanceled: true}) : reject(error)
);
});
return {
promise: wrappedPromise,
cancel() {
isCancelled = true;
},
};
};
create a variable for the request outside your useEffect
为您的
useEffect
之外的请求创建一个变量
let fetchTeamsRequest = null;
and updated your useEffect
function like below.并更新了您的
useEffect
function,如下所示。
useEffect(() => {
const getTeams = async () => {
if (fetchTeamsRequest) {
try {
await fetchTeamsRequest.promise;
return;
} catch (error) {
return;
}
}
fetchTeamsRequest = makeCancellable(fetchContext.authAxios.get('get-all-teams'));
try {
const teams = await fetchTeamsRequest.promise;
fetchTeamsRequest = null;
setIsLoaded(true);
if (isLoaded === true) {
if (!fetchTeamsRequest.isCancelled) {
fetchContext.setTeamList(teams.data);
}
}
} catch (error) {
if (!fetchTeamsRequest.isCancelled) {
fetchTeamsRequest = null;
console.log(error);
}
}
};
getTeams();
return () => {
if (fetchTeamsRequest) {
fetchTeamsRequest.cancel();
}
};
}, [fetchContext, isLoaded]);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.