'Why don't work this cleanup function with the useState hook, only with the useRef hook?
I know that when the useRef is changed, then the component won't be re-rendered, anyway, can you explain me what happens exactly in each version? In the useEffect function the isCan.current will be set to true, if the component is unMounted. When it is unmounted the dispatch function and a couple of state won't be chenged (if condition in the try block). In this way it works, but can you tell me why does not work all this code with the state hook (isCancelled)?
with useRef: So when the component is unmounted, the
isCan.currentwill be immediately set totrue. If cancellation happened before the if condition, the dispatch and some hooks won't be changed, because theisCannow istrue.with useState: When the component is unmounted, the
isCancelledwill be immediately set totrue. But unlike to theuseRef, it will always go in the if condition and the sates will be changed. (of course the if condition this time isif(!isCancelled))
Can you tell me why is the isCancelled still false after the cleanup function?
import { useEffect, useRef, useState } from 'react';
import { auth } from '../firebase/config';
import { signInWithEmailAndPassword } from 'firebase/auth';
import { useAuth } from '../context/AuthContext';
export const useLogin = () => {
const isCan = useRef(false);
// const [isCancelled, setIsCancelled] = useState(false);
const [error, setError] = useState(null);
const [isPending, setIsPending] = useState(false);
const { dispatch } = useAuth();
const login = async (email, password) => {
setError(null);
setIsPending(true);
console.log(123);
//sign user out
try {
const res = await signInWithEmailAndPassword(auth, email, password);
//update state
if (!isCan.current) {
dispatch({ type: 'LOGIN', payload: res.user });
console.log('asdf');
setIsPending(false);
setError(null);
}
} catch (error) {
if (!isCan.current) {
console.log(error.message);
setError(error.message);
setIsPending(false);
}
}
};
useEffect(() => {
return () => {
// setIsCancelled(true);
isCan.current = true;
console.log('is cancel:', isCan.current);
};
}, []);
return { login, error, isPending };
};
Solution 1:[1]
There are two good points that should be mentioned here:
1 - First of all, answering to your question, states updates are asynchronous, so when you set a new state value and console.log() right after it, it's going to show the previous value, because the state hasn't been updated yet. That's why your isCancelled value is false.
2 - You're trying to set a new state to isCancelled on useEffect cleanup function, but this state is being declared inside your useLogin hook, and like I said, the state update is async, so you'll probably see this warning on your console, because the component is going to be unmounted when the state update would happen:
Warning: Can't perform a React state update on an unmounted component.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Gustavo Galupo |
