0
votes

I'm working with react and I'm trying to set state on page render but it keeps throwing the below 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.

---Error----

Below is my code of the sidebar component. I'm using Context API for data management as shown in the code and I'm trying to set state of the role inside the showContext method with the value I'm getting through the Context API Consumer.

import React, { Component, PropTypes } from "react";
import { Menu, Icon } from "antd";
import { BrowserRouter as Router, Link, Route, Switch } from "react-router-dom";
import AdminPage from "../components/Admin/AdminPage";
import App from "../App";
import "../components/Login/LoginPage";
import { LoginContext } from "../context/LoginContext";

export default class MainMenu extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      roleValue: "admin",
      status: false
    };
    this.showContext = this.showContext.bind(this);
  }

  showContext(context) {

    let role = context;

    if (this.state.roleValue == role) {
      this.setState({
         roleValue : "admin",
      });
    }

  }


  render() {


    if (window.location.href == "http://localhost:8081/") {
      var loginHeader =
        <Menu        
          theme="dark"
          mode="horizontal"
          defaultSelectedKeys={["2"]}
          selectedKeys={[location.pathname]}
        >
          {this.props.children}
          <Menu.Item key="mastering">Mastering</Menu.Item>     
        </Menu>;


    }

    else {
      if (this.state.roleValue == "general") {
        var generalHeader1 =
          <Menu      
            theme="dark"
            mode="horizontal"
            defaultSelectedKeys={["2"]}
            selectedKeys={[location.pathname]}
          >
            {this.props.children}
            <Menu.Item key="mastering">Mastering</Menu.Item>

            <Menu.Item>
              <Link to="/"> Logout</Link>
            </Menu.Item>

            <Menu.Item>
              <Link to="/home">Home</Link>
            </Menu.Item>         
          </Menu>;

      }

      else {
        var generalHeader2 =
          <Menu        
            theme="dark"
            mode="horizontal"
            defaultSelectedKeys={["2"]}
            selectedKeys={[location.pathname]}
          >
            {this.props.children}
            <Menu.Item key="mastering">Mastering</Menu.Item>

            <Menu.Item>
              <Link to="/"> Logout</Link>
            </Menu.Item>

            <Menu.Item>
              <Link to="/admin">Admin</Link>
            </Menu.Item>

            <Menu.Item>
              <Link to="/home">Home</Link>
            </Menu.Item>

          </Menu>;


      }
    }


    return (
      <div>

        {loginHeader}
        {generalHeader1}
        {generalHeader2}

        <LoginContext.Consumer>
          {(context) => (
            this.showContext(context.state.role)
          )
          }
        </LoginContext.Consumer>


      </div>
    );


  }
}
5

5 Answers

0
votes

setState() causes a call to render(). So if you call setState() in render() you will get infinite recursion. DON'T DO THIS. Instead find the correct way to do what you want within the framework defined by React and the other libraries you use.

0
votes

A React component waits for any change on its own state and props in a normal conditions and when a changes takes place, it calls Render method and expect a component or null to be returned.

What you did is: Component starts and tries to do its very first render and you set component states which request another render and it set states again and it goes on like this. It calls each other circularly.

Set state outside of Render method to avoid this situation.

0
votes

You are doing it in wrong way, as you are setting the state inside the render the render loop will be infinite.

Please check this link which will help you to resolve your problem, and still if you face any issue after implementation let me know I will love to help you.

Reference link : https://reactjs.org/docs/context.html#dynamic-context

0
votes

Use React lifecycle method componentDidMount to handle such tasks related to setState.

0
votes

In you are code you have written code in your render which is not good practices. Please remove code from render and add it into componentDidMount. Use componentDidMount() lifecycle which will make your life easy the code should be something like below.

 componentDidMount() {
     this.showContext(this.state.roleValue)
 }

As I have seen you have different side bar for each user. The best thing you can do in this create separate component for each role for sidebar and show that particular component as role wise.