Use setState () properly in React

Use setState () properly in React

In this post, we’re going to explore the safest ways to set state in React. Inside of which lifecycle methods is it alright to set a component’s state and where are you going to create an infinite loop?

Using setState in React in the right way is very important. Data flows from top to bottom in the component tree. If we set the state in the top component, all the child components are re-rendered. Setting this state in the wrong way triggers an infinite loop among components which will break our application.

In this post, we’re going to explore the safest ways to set state in React.

Initial Rendering

In this phase, components are loaded for the first time in the DOM. Let’s see each method whether we can set the state or not.

Constructor

Safe to use setState? No!

The constructor is the first lifecycle method to be called when the component is loaded. This is where we set the initial props and state of the component. So it makes sense that this is the right place to initialize the state of the component.

componentWillMount()

Safe to use setState? Yes!

In componentWillMount we can access the initial props and state that is defined in the constructor here. We get the chance to modify the state here before we render the UI for the first time.

render()

Safe to use setState? No!

In render, we can access the props and state here but we can’t set the state here. We can actually modify the data by assigning the data from props and state to a different variable. In this way, We have a chance of displaying data in the DOM as needed. Since it is assigned to a different variable, whatever changes done to this variable doesn’t affect the state or props.

For instance, look at the following example we want to display the name in uppercase in UI. We can do that by calling _toUpperCase()_ on _this.state.name_ and assigning that to the variable called name.

render() {

    const name = this.state.name?this.state.name.toUpperCase():'';

    return (
      <div className="App">
        <header className="App-header">
        </header>
        <div> 
            <p>{name}</p>
            <a href="#" onClick={() => this.togglePerson()}>toggle address</a>
            <div>
            <label>Change address</label>
            <input id="sff" type="text" onChange={(e) => this.changeAddress(e)}></input>
            </div>
            {this.state.showPerson?<Person address={this.state.address} />:""}
        </div>
      </div>
    );
  }

App.js

componentDidMount()

Safe to use setState? Yes!

We can access props and state that is defined in the constructor and modified in preceding methods here. We can modify the state here to render the UI final time before ending the initial rendering phase. Since componentDidMount() only occurs one time, it is safe to set the state here.

In Action

If we look at the gist below, this.setState() is used to change the name in componentWillMount() and componentDidMount() and the final name is reflected on the screen. An important thing to note here isthat as stated before, componentDidMount() occurs only once to give a render a second pass. That’s why it is safe to use setState there and we shouldn’t use it in render().

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import Person from './Person'

class App extends Component {

  constructor(props){
      super(props)

      console.log("in the constructior")

      this.state = {
          name: "Bhargav Bachina",
          age: 15,
          address: "2222 some street somecity ST, 77777",
          showPerson: true
      }
  }

  togglePerson() {
     this.setState({showPerson: !this.state.showPerson});
  }

  changeAddress(e) {
     this.setState({address: e.target.value});
  }

  // only called once before render() and we can setState() here
  componentWillMount() {
      console.log("This is called before component instance and before render() function")
      if(this.state.age === 15) {
         console.log("I am 15!!!")
      }
      this.setState({name:"I am changed in componentWillMount"})
  }

  // only called once after render() and we can setState() here
  componentDidMount() {
    console.log("This is called after render() function")
    if(this.state.age === 15) {
       console.log("I am 15!!!")
    }
    this.setState({name:"I am changed again!!"})
}

  render() {

    console.log("this is from render()")
    const name = "From render()::" + this.state.name

    return (
      <div className="App">
        <header className="App-header">
        </header>
        <div> 
            <p>{name}</p>
            <a href="#" onClick={() => this.togglePerson()}>toggle address</a>
            <div>
            <label>Change address</label>
            <input id="sff" type="text" onChange={(e) => this.changeAddress(e)}></input>
            </div>
            {this.state.showPerson?<Person address={this.state.address} />:""}
        </div>
      </div>
    );
  }
}

export default App;

setState is used in componentWillMount and componentDidMount

Try to use setState() in render() and you will get the following error because you’ve created an infinite loop:

usage of setState() in render throws error

Rendering When Props Change

component lifecycle when props change

In this phase, components are re-rendered every time there is a change in the props. Let’s see each method whether we can set the state or not.

componentWillReceiveProps()

Safe to use setState? Yes!

This method is called whenever there is a change in the props. this method has an argument called nextProps can be compared with current props. This method only occurs once so, it is safe to call this.setState() in this method.

shouldComponentUpdate()

Safe to use setState? Yes!

This method is called whenever there is an update in the props or state. This method has arguments called nextPropsandnextStatecan be compared with current props and currentState. we can take a decision whether we can do re-rendering or not by returning a boolean value from this method. This method only occurs once so, it is safe to call this.setState() in this method.

componentWillUpdate()

Safe to use setState? No!

This method is called whenever there is a re-render. So, if we use setState() here that triggers re-render again which leads to an infinite loop. never use setState() here.

render()

Safe to use setState? No!

We can access the props and state here but we can’t modify it here. if we want to modify anything before displaying it on the DOM, we need to assign that to a variable and do that. We can’t set the state here.

componentDidUpdate()

Safe to use setState? Yes with the condition!

This method is called whenever there is a re-render. So, if we use setState() here that triggers re-render again which leads to an infinite loop. But, As M Coghlan mentioned in the comments we can do conditional rendering by comparing previous props and next props like below. In this way, we can avoid an infinite loop.

componentDidUpdate(prevProps, prevState) {
   if(prevProps.userStatus !== this.props.userStatus) {
      this.setState({userStatus: this.props.userStatus})
   }
}

Rendering When State Changes

component lifecycle when state changes

In this phase, the same applies here. The only difference between is componentWillReceiveProps() which occurs only there is a change in the props.

Conclusion

As discussed above, please remember not to use setState in render, componentWillUpdate and componentDidUpdate which lead to an infinite loop and throw an error.

Thank you for reading and Happy coding!

Angular 9 Tutorial: Learn to Build a CRUD Angular App Quickly

What's new in Bootstrap 5 and when Bootstrap 5 release date?

Brave, Chrome, Firefox, Opera or Edge: Which is Better and Faster?

How to Build Progressive Web Apps (PWA) using Angular 9

What is new features in Javascript ES2020 ECMAScript 2020

Hire React Js Developer from Expert React JS Development Company

Are you looking to [hire React JS developer](https://www.mobiwebtech.com/react-js-development-company/ "hire React JS developer") from a prestigious and reliable React JS development company? Visit at Mobiweb Technologies here we have a big team...

Functional Programming for JavaScript Developers

Functional Programming for JavaScript Developers. Learn Functional Programming and how it enables developers to move from imperative to declarative programming. Solidify your knowledge of functional JavaScript programming, including objects, arrays, and prototypes. Learn higher-order functions, closures, scope, master key functional methods like map, reduce and filter and promises and ES6+ asynchronous JavaScript. Learning how to build and manage asynchronous functional programs is perhaps the most important part of becoming an effective JavaScript programmer.

React Native App Development Company in New York

Hire top react native app development company in New York to build and develop custom react native mobile apps for Android & iOS with the latest features.