Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state. in Index.js
Asked Answered
S

1

12

I'm using react and react hooks for front-end and I'm getting this error:

index.js:1 Warning: Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.
    in Login (created by Context.Consumer)
    in Route (at App.js:46)
    in AuthContextProvider (at App.js:37)
    in Switch (at App.js:36)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:32)
    in div (at App.js:30)
    in App (at src/index.js:9)
    in StrictMode (at src/index.js:8)
console.<computed> @ index.js:1
overrideMethod @ react_devtools_backend.js:2273
printWarning @ react-dom.development.js:88
error @ react-dom.development.js:60
warnAboutRenderPhaseUpdatesInDEV @ react-dom.development.js:23250
scheduleUpdateOnFiber @ react-dom.development.js:21165
enqueueSetState @ react-dom.development.js:12639
push../node_modules/react/cjs/react.development.js.Component.setState @ react.development.js:471
(anonymous) @ Router.js:34
listener @ history.js:155
(anonymous) @ history.js:173
notifyListeners @ history.js:172
setState @ history.js:288
(anonymous) @ history.js:369
confirmTransitionTo @ history.js:145
push @ history.js:350
Login @ Login.js:66
renderWithHooks @ react-dom.development.js:14803
mountIndeterminateComponent @ react-dom.development.js:17482
beginWork @ react-dom.development.js:18596
beginWork$1 @ react-dom.development.js:23179
performUnitOfWork @ react-dom.development.js:22154
workLoopSync @ react-dom.development.js:22130
performSyncWorkOnRoot @ react-dom.development.js:21756
(anonymous) @ react-dom.development.js:11089
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11039
flushSyncCallbackQueueImpl @ react-dom.development.js:11084
flushSyncCallbackQueue @ react-dom.development.js:11072
discreteUpdates$1 @ react-dom.development.js:21893
discreteUpdates @ react-dom.development.js:806
dispatchDiscreteEvent @ react-dom.development.js:4168
Show 2 more frames from Library code

Login.js:

import React ,{useState, useContext}from 'react';
import {useHistory} from 'react-router-dom'
import axios from 'axios'
import '../CSS/Ninety.css'
import { AuthContext } from '../../contexts/AuthContext';


const Login = () => {

    const history=useHistory()
    const {authLog,dispatch} = useContext(AuthContext)
    const [Login,setLogin] = useState({
        email:'',
        password:'',
        
    })

    const [response, setResponse] = useState({
        email: '',
        password: ''
    });
    
    const handleSubmit=(e)=>{
        e.preventDefault()
        axios.post('http://localhost:2000/apiEndpoint/CREATE/user/login', {
            
            email:Login.email,
            password:Login.password
          },{withCredentials:true},{
            headers: {
                  'Content-Type': 'application/json'
      }
          
          
        })
          .then(function (res) {
              if(res.data.token){
                  console.log('SUCCESS', res.data)
                  dispatch({type: 'LOGIN', payload: res.data});
                    history.push('/blog')
              }else{
                console.log('ERRORS',res.data)
                setResponse({...response, email: res.data.email, password: res.data.password})
              }
            })
        
        setResponse({...response, email: '', password: ''})   

        
        
    }

    


    const handleChange=(e)=>{
        const {name,value}=e.target
        setLogin({ ...Login, [name]: value });
        
            
    } 
    console.log('AUTH LOG',authLog)
if(authLog.isAuthenticated){

    console.log('You are authenticated and are being redirected to blog')
    history.push('/blog');
        return null
    
}else{
    return(
    
        <div className='ninetyPer'>
        <form onSubmit={handleSubmit}>
            <h1>Login up:</h1>
            
                
            <label name='email'>email:</label>
            <input name='email' onChange={handleChange} value={Login.email}></input>
                <h5>{response.email}</h5>
            <label name='password'>password:</label>
            <input name='password' onChange={handleChange} value={Login.password}></input>
                <h5>{response.password}</h5>
            <button>Submit</button>
        </form>
        </div>
    
        )
}
    
    
};

 
export default Login;

That error has something to do with this in Login.js

....
if(authLog.isAuthenticated){

    console.log('You are authenticated and are being redirected to blog')
    history.push('/blog');
        return null
    
}else{
....

App.js:

import React, { Component } from 'react';
import CreateArticle from './components/Pages/CreateArticle'
import Blog from './components/Pages/Blog'
import Navbar from './components/Navbar.js';
import ApiReceiver from './components/new.component'
import {BrowserRouter as Router, Route, Switch, withRouter, Link} from 'react-router-dom'
import Home from './components/Pages/Home'
import About from './components/Pages/About'
import Contact from './components/Pages/Contact'
import Singup from './components/Pages/Signup'
import Login from './components/Pages/Login'

import AuthContextProvider from './contexts/AuthContext';

class App extends React.Component{
  constructor(props){
  super(props);
  this.state= {
    posts:[ 
      
    ]
  
}}



render() {

  return (
    <div className="App">
    
      <Router>
        
        <Navbar />
        
        <Switch>
        <AuthContextProvider>
          <Route path="/" exact component={Home} />

          <Route path="/blog/create" exact component={CreateArticle} />

          <Route path="/blog" component={Blog} />

          <Route path="/user/signup" component={Singup} />
              
          <Route exact path="/user/login" component={Login} />
          

          <Route path="/about" component={About} />
          <Route path="/contact" component={Contact} />
          </AuthContextProvider>
        </Switch>
        
      </Router>
      
      
      
      
      
    </div>
  );
}
}



export default App;

Index.js:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css'
import App from './App';


ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

I'm using history.push to redirect to another page if my login is authenticated.

In spite of the error, the website is still running but I have this WARNING ERROR.

Stevestevedore answered 11/10, 2020 at 17:22 Comment(5)
Instead of history.push, try using the Redirect component from react-router-dom instead. So instead of history.push('/blog');, try return <Redirect to="/blog" />Narcolepsy
It did work. Thanks alot. Can you also explain to me why this happens? Also im getting a new error:index.js:1 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 the componentWillUnmount method. in ArticleCard (at Blog.js:21) in div (at Blog.js:19) in Blog (created by Context.Consumer)Stevestevedore
Blog.js: import React, { Component } from 'react'; import ArticleCard from '../ArticleCard' import '../CSS/Ninety.css' import '../CSS/Blog.css' import { Redirect } from 'react-router-dom'; const axios = require('axios').default; class Blog extends Component{ state={ } render(){ return ( <div className='ninetyPer'> BLog Page <ArticleCard /> </div> ) } } export default BlogStevestevedore
It's because if you change the path in the middle of a render, React Router will be notified of the path change and will try to start updating props. This is an example of a "side effect" in the context of "render() must not have side-effects". However, by returning the <Redirect/> component, you finish the render() and the redirect happens after the component finishes rendering.Narcolepsy
As for the other issue, I would suggest searching for that warning (see this question for example), and if you don't find helpful answers, open a new question for your case.Narcolepsy
N
25

That history.push() will introduce side-effects in the render method. In this case, it will make React Router try to start updating props to reflect the new path, which triggers the error you see.

Instead of using history.push(), use the <Redirect /> component from react-router-dom instead:

if(authLog.isAuthenticated){

    console.log('You are authenticated and are being redirected to blog')
    return <Redirect push to="/blog" />
}

By rendering the Redirect component, the redirect occurs after the component finishes rendering, meaning that the updates made by React Router don't happen in the middle of a render.

EDIT: As mentioned in the comments by @TimIles, adding the push prop will make the <Redirect> act as a history.push() instead of history.replace().

Narcolepsy answered 11/10, 2020 at 18:10 Comment(4)
This works, but what if i want to store history as well, how can i achieve?Swivel
@KannanT You can create a custom history object for the <Router> component (reactrouter.com/web/api/Router/history-object) and listen to its changes with history.listen()Narcolepsy
@KannanT To add your redirection to the browser history as well, set the push attribute, as in return <Redirect push to="/blog" />Admittance
@TimIles Great addition, I've edited the answer to include that.Narcolepsy

© 2022 - 2024 — McMap. All rights reserved.