WebDevSimplified / React-Firebase-Auth

637 stars 439 forks source link

Warning: Can't perform a React state update on an unmounted component #3

Open raelb opened 3 years ago

raelb commented 3 years ago

Hi Kyle, Thanks for the super tutorial.

I just wanted to point out, when you move from the login page to the dashboard, the console shows a warning:

image

It looks like the problem is caused (in Login.js) by setting state after call to history.push which already moves to the Dashboard component.

  async function handleSubmit(e) {
    e.preventDefault()

    try {
      setError('')
      setLoading(true)
      await login(emailRef.current.value, passwordRef.current.value)
      history.push('/')
    } catch {
      setError('Failed to sign in')
    }
    setLoading(false)   // --> problem
  }

Is the correct solution to just remove call to setLoading, or is there a better solution?

magusfabius commented 3 years ago

Hi @raelb ! I was stuck in the same problem and after some research I understand that the setLoading was called after the history.push, and as I understand, when you call history.push you unmount the component (in this case Login) but the function handleSubmit have to terminate and it executes setLoading on something that doesn't exists anymore.

I edited the code like this, and it works:

async function handleSubmit(e){
        e.preventDefault()

        try {
            setError('')
            setLoading(true) 
            await login(emailRef.current.value, passwordRef.current.value)
            setLoading(false)  
            history.push('/home')
        } catch {
            setLoading(false)  
            setError('Failed to login')
        }
}

This answer enlighted me, but I'd like to know if my conclusions are right :)

devwax commented 3 years ago

I had the same problem, but my issue was that I was using the de-structuring curly braces when setting history from useHistory() in Dashboard.js. That was causing history to be undefined.

https://github.com/WebDevSimplified/React-Firebase-Auth/blob/c3554089313682dc0f216adb38d4ccf3addcd39f/src/components/Dashboard.js#L9

It's an easy mistake given that so many hooks require de-structured assignment syntax. e.g. https://github.com/WebDevSimplified/React-Firebase-Auth/blob/c3554089313682dc0f216adb38d4ccf3addcd39f/src/components/Dashboard.js#L7-L9

dhruvangg commented 3 years ago

I'm getting same error while using REST API Login. How can I use useEffect function while working with API.

`export function AuthProvider({ children }) {

const [currentUser, setCurrentUser] = useState()
const [loading, setLoading] = useState(false)

async function signup(email, password) {
    console.log("Signup");
}

async function login(email, password) {
    try {
        const resp = await axios.post('http://localhost:8080/api/login', {
            email, password
        })
        console.log(resp.data);
        setCurrentUser(resp.data.token)
    } catch (error) {
        console.log(error);
    }
}

function logout() {
    console.log("Logout");
    // return auth.signOut()
}

const value = {
    login,
    signup,
    logout,
    currentUser
}

return (
    <AuthContext.Provider value={value}>
        {!loading && children}
    </AuthContext.Provider>
)

}`

devwax commented 3 years ago

@dhruvangg I would try moving the async login handling to Login.js. Only return the axios.post promise to login(). Then handle the async/await in the handleSubmit() function in Login.js.

The problem with that is that you will need a way to setCurrentUser from Login.js. To do that I would export setCurrentUser in AuthContext.js (in the value attribute like the rest). Then import it in Login.js from useAuth along with the login function so you can use it in handleSubmit().

In other words, you probably don't need useEffect for axios.post. The reason it was used for auth.onAuthStateChanged was so that the listener can be unsubscribed when the component is destroyed. axios.post doesn't set a listener. It just returns a promise.

I suppose you could useEffect in Login.js and set it's dependency to currentUser, but I'm new to React hooks myself and haven't played with it that much yet. Just some thoughts.

Shemmmmm commented 9 months ago

Good progress. Keep up the good work.