0
votes

i'm new in react native and i have an error i can't understand, the console sends a message that 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 %s.%s, a useEffect cleanup function

My code is the next

const AuthStack = createStackNavigator();

const LoginStack = () => {

    const initialLoginState = {
        isLoading: true,
        userName: null,
        userToken: null,
    };

    const loginReducer = (prevState, action) => {
        switch (action.type) {
            case 'RETRIEVE_TOKEN':
                return {
                    ...prevState,
                    userToken: action.token,
                    isLoading: false,
                };
            case 'LOGIN':
                return {
                    ...prevState,
                    userName: action.id,
                    userToken: action.token,
                    isLoading: false,
                };  
            case 'LOGOUT':
                return {
                    ...prevState,
                    userName: null,
                    userToken: null,
                    isLoading: false,
                };
        }
    };
    
    const [loginState, dispatch] = useReducer(loginReducer, initialLoginState);

    const authContext = useMemo(() => ({
        signIn: (userName, password) => {
            let userToken;
            userName = null;
            if ( userName == 'user' && password == 'pass' ) {
                userToken: 'irais';
            }
            dispatch({ type: 'LOGIN', id: userName, token: userToken });
        },
        signOut: () => {
            dispatch({ type: 'LOGOUT' });
        },
    }));

    useEffect(() => {
        setTimeout(() => {
            // setIsLoading(false)
            dispatch({ type: 'RETRIEVE_TOKEN', token: 'irais' });
        },1000);
    }, []); 
}
2

2 Answers

1
votes

The issue is 'useEffect'. You need to return a clean up function to make sure that any effects are disposed of properly.

 useEffect(() => {
        const handle = setTimeout(() => {
            // setIsLoading(false)
            dispatch({ type: 'RETRIEVE_TOKEN', token: 'irais' });
        },1000);
        
        return () => clearTimeout(handle);
    }, []); 
1
votes

Take a look at your useEffect. It schedules an async task (timeout) which updates the component state (using dispatch). Then, it is possible that your component already mounted when this timeout fullfils. The solution is to use a cleanup function, which is basically the return statement of useEffect:

   useEffect(() => {
        const timeout = setTimeout(() => {
            // setIsLoading(false)
            dispatch({ type: 'RETRIEVE_TOKEN', token: 'irais' });
        },1000);

        return () => {
           clearTimeout(timeout);
        }
    }, []);