简体   繁体   中英

React render - Infinite loop happenes sometimes

I have a simple login component which works fine (ie it redirects to dashboard most of the times after successful login). However, sometimes out of blue, it throws an error:

Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

Here're my code. Please note that when the error happnens, I notice, <Redirect to={routes.DASHBOARD}/> this gets called, but instead of redirecting to this component, the same login component keeps getting called infinitely.

import React, { useState } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Redirect } from 'react-router';
import { login } from '../../redux/actions';
import styles from './login.module.css';
import {routes} from '../../routes';

export function Login() {
  const { user } = useSelector((state) => state);
  const dispatch = useDispatch();

  const [email, setEmail] =useState('');
  const [password, setPassword] = useState('');
  const handleLogin = ()=>{
      dispatch(login({email, password}))
  }

  const handleEmailInput = (e)=>{
      setEmail(e.target.value)
  }

  const handlePasswordInput = (e)=>{
      setPassword(e.target.value)
  }

  if((user.tokenReceived || localStorage.getItem('token')) && !user.tokenExpired){
    return <Redirect to={routes.DASHBOARD}/>
  }

  return (
    <div>
      <div className={styles.row}>

          <input type='text' placeholder="Email" onChange={handleEmailInput}/>
          <input type='text' placeholder="Password" onChange={handlePasswordInput}/>

        <button
          className={styles.loginButton}
          onClick={handleLogin}
        >
          Login
        </button>
        {user.error && "Some Error occurred. Please try again"}
      </div>
    </div>
  );
}

I'm pretty sure I'm doing the right way, but should I be wrapping this under useEffect ,

if((user.tokenReceived || localStorage.getItem('token')) && !user.tokenExpired){
    return <Redirect to={routes.DASHBOARD}/>
  } 

I think your problem lays when you call handleLogin function on button click. Call the function as an arrow function.

<button
     className={styles.loginButton}
     onClick={() => handleLogin()}
>

Every time you update a state, the page is re-rendered. It means that every time you update a state, this if is called.

Use a UseEffect to validate data when user just access the page.

useEffect(() => {
  if((user.tokenReceived || localStorage.getItem('token')) && !user.tokenExpired){
    return <Redirect to={routes.DASHBOARD}/>
  } 
}, [])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM