Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
raelb opened this issue Oct 27, 2020 · 5 comments
Open

Comments

@raelb
Copy link

raelb commented Oct 27, 2020

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
Copy link

magusfabius commented Dec 7, 2020

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
Copy link

devwax commented Dec 27, 2020

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.

const history = useHistory()

It's an easy mistake given that so many hooks require de-structured assignment syntax. e.g.

const [error, setError] = useState("")
const { currentUser, logout } = useAuth()
const history = useHistory()

@dhruvangg
Copy link

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
Copy link

devwax commented Dec 31, 2020

@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.

qyangaa added a commit to qyangaa/tele_pain_center that referenced this issue Jan 8, 2021
@Shemmmmm
Copy link

Good progress. Keep up the good work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants