最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - I get Error: Can't perform a React state update on an unmounted component even though i created cleanup - S

programmeradmin2浏览0评论

An error keeps bothering me on my app says

Warning: Can't perform a React state update on an unmounted ponent. 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.

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 .

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.

Here is my code in 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;

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

An error keeps bothering me on my app says

Warning: Can't perform a React state update on an unmounted ponent. 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.

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 .

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.

Here is my code in 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;

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

Share Improve this question edited Mar 25, 2021 at 2:16 Junaire Edris Badiang Buico asked Mar 25, 2021 at 2:10 Junaire Edris Badiang BuicoJunaire Edris Badiang Buico 491 gold badge1 silver badge8 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 3

Well, you can use the React remended way to fix this issue. All you need to do is wrap your api call within makeCancellable method and cancel them when your ponent is unmounting.

Ref: https://reactjs/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

let fetchTeamsRequest = null;

and updated your useEffect function like below.

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]);

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论