dev
dev

Reputation: 133

How to update component state in function react js?

I have two components

I want to display username after login in header.

Below is code...

class Header extends Component {

    constructor(props) {

        super(props); 

        this.state = {         
          isLoggedIn: false
        };  
      }

    isLoggedIn = () => {    

        var flag = localStorage.getItem('loggedUser') !== null; 
        this.setState({isLoggedIn : flag}); // this line gives error
        return flag;
    }


  render() {

    if(this.isLoggedIn() == true){

    return(
      <div>
           <div className="header">          
              <div className="headerUser">Logged in as: {localStorage.getItem("loggedUser")}</div>
              <img src={Logo} className="app-logo" alt="logo" width="145" height="55" />
           </div>
      </div>
     );

    } else {

    return(
      <div>
           <div className="header">                       
              <img src={Logo} className="app-logo" alt="logo" width="145" height="55" />
           </div>
      </div>
     );

    }

    }
}
export default Header;

How to change state inside function as it does not allow me to use this keyword..?

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.

Upvotes: 0

Views: 1511

Answers (4)

kiranvj
kiranvj

Reputation: 34107

Your code has entered a render loop since setState is indirectly called from render(). render() is called after a setState call

Load the required data in componentDidMount() and set its value in state and check for the state value in render, and don't use multiple return see the below code.

class Header extends Component {

    constructor(props) {

        super(props); 

        this.state = {         
          isLoggedIn: false
        };  
      }
    componentDidMount() {
       var flag = localStorage.getItem('loggedUser') !== null; 
       this.setState({isLoggedIn : flag}); 
    }    


  render() {

    return(
      { this.state.isLoggedIn ?
        <div>
           <div className="header">          
              <div className="headerUser">Logged in as: {localStorage.getItem("loggedUser")}</div>
              <img src={Logo} className="app-logo" alt="logo" width="145" height="55" />
           </div>
      </div>

    : <div>
           <div className="header">                       
              <img src={Logo} className="app-logo" alt="logo" width="145" height="55" />
           </div>
      </div>

    })
  }
}
 export default Header;

return() can be further optimized like this

 return(

        <div>
           <div className="header">          
              { this.state.isLoggedIn ?<div className="headerUser">Logged in as: {localStorage.getItem("loggedUser")}</div> : null }
              <img src={Logo} className="app-logo" alt="logo" width="145" height="55" />
           </div>
      </div>

)

Upvotes: 1

Stephan Hovius
Stephan Hovius

Reputation: 391

Well Here is your answer...

class Header extends Component {
    constructor(props) {
        super(props);
        this.state = {
            isLoggedIn: false
        };
    }

    isLoggedIn = () => localStorage.getItem('loggedUser') !== null;

    render() {
        if(this.isLoggedIn()) {
            return(
                <LoggedIn onMount={() => this.setState({isLoggedIn: this.isLoggedIn()})} />
            );
        } else {
            return(
                <div>
                    <div className="header">
                        <img src={Logo} className="app-logo" alt="logo" width="145" height="55" />
                    </div>
                </div>
            );
        }
    }
}
export default Header;

class LoggedIn extends Component {
    componentWillMount() {
        this.props.onMount();
    }
    render() {
        return (
            <div>
                <div className="header">
                    <div className="headerUser">Logged in as: {localStorage.getItem("loggedUser")}</div>
                    <img src={Logo} className="app-logo" alt="logo" width="145" height="55"/>
                </div>
            </div>
        )
    }
}

export default LoggedIn;

Upvotes: 0

bmovement
bmovement

Reputation: 867

You’re setting state in your isLoggedIn method,, which triggers another render, which calls isLoggedIn again, etc. You should just check the state object in render directly (this.state.isLoggedIn), and you should set the state only at the beginning, or when your user’s state changes.

Upvotes: 0

Joey Gough
Joey Gough

Reputation: 3103

you're calling setState while rendering... try like

class Header extends Component {

constructor(props) {

    super(props); 

    this.state = {         
      isLoggedIn: false
    };  
  }

isLoggedIn = () => {    

    var flag = localStorage.getItem('loggedUser') !== null; 
    // this.setState({isLoggedIn : flag}); // delete here 
    return flag;
}


  render() {

if(this.isLoggedIn() == true){

return(
  <div>
       <div className="header">          
          <div className="headerUser">Logged in as: {localStorage.getItem("loggedUser")}</div>
          <img src={Logo} className="app-logo" alt="logo" width="145" height="55" />
       </div>
  </div>
 );

} else {

return(
  <div>
       <div className="header">                       
          <img src={Logo} className="app-logo" alt="logo" width="145" height="55" />
       </div>
  </div>
 );

}

}
}
export default Header;

Upvotes: 0

Related Questions