React setState: setstate Objects and Callback Functions

Read it in 7 Mins

Published
23rd Dec, 2022
Views
1,272
React setState: setstate Objects and Callback Functions

Equipping yourself with the necessary skills to effect DOM changes is a matter that should not be trivialized. React.js, class-based programming, is different from functional-based programming. In functional-based React development, we use the React hook called useState(). But what if you need to work with a class-based component? How would you resolve this problem? Learn how to work with React setState() and other app dev practices with our app development course for beginners to advance your software development skills. 

In this tutorial, you will learn how to use React setState() to effect updates to the DOM using a class-based approach. So, if you are ready, let us jump into the tutorial... 

Basic Concepts of setState( )

State in React is an object that contains data or information about the component. React state can change during a component's life, and whenever it does, the component re-renders. The state can change in response to user action or system-generated events, and these changes determine how the component behaves and renders. The data contained in a React state can be used to monitor activities and cause changes to the DOM. 

Here is a quick example of how ReactJs setState() works below. 

import React, { Component } from "react"; 
import "./styles.css"; 
class Generate extends React.Component { 

 constructor() { 
    super(); 
    this.state = { 
      pin: 0 
    }; 
    this.generateNum = this.generateNum.bind(this); 
  } 
  generateNum() { 
    const luky_num = Math.floor(Math.random() * (100 - 1 + 1)) + 1; 
    this.setState({ pin: luky_num }); 
  } 
render() { 
    return ( 
      <div> 
        <h4>What's the luky number</h4> 
        <p> 
          The luky number is: <span className="result">{this.state.pin}</span> 
        </p> 
        <button onClick={this.generateNum}>Get Luky</button> 
      </div> 
    ); 
  } 
}  
export default Generate; 

Note from the above example that: 

  • A state can be changed because of user action or network changes. 
  • When an object's state changes, React re-renders the component in the browser. 
  • A constructor, a leading function, is used to initialize a state object. 
  • The state object can store a variety of properties. 
  • We use this.setState() is used to modify a state object's value. 
  • The setState() function performs a shallow merge of the current and previous states. 

If you are interested in exploring React JS in-depth, we encourage you to sign up for React native online course and upskill yourself. 

Three Rules of Thumb When Using setState( )

Rule 1: Do not change state directly 

Never change a state variable directly, always use a function to change a state's value, as seen in the code below. 

//wrong 
this.state.inputValue = e.target.value; 
//correct 
this.setState({inputValue:e.target.value}) 

Rule 2: State Updates may be asynchronous 

When the update of a state variable results in an asynchronous request, you should always put this request in a callback function. Observe the code example below. 

changeName = async(e) => { 
  await this.checkAvailability(e.target.value) 
}; 
checkAvailability = async(username) => { 
  setTimeout(() => { 
    if(username.includes('a')) { 
      this.setState({ isAvail: true }); 
    }else { 
      this.setState({ isAvail: false }); 
    } 
    this.setState({ name: username }); 
    console.log(this.state.isAvail) 
  }, 5000); 
} 
 
Rule3: State Updates are Merged 
Minimize using multiple this.setState() in one function, instead perform their updates in one execution. See the example below: 
//Wrong approach 
if(this.state.inputValue === ''){ 
   this.setSatte({name: 'David'}) 
   this.setSatte({age: 25}) 
   this.setSatte({metadata: {nationality: 'India', gender: 'male'}}) 
} 
//right approach 
if(this.state.inputValue === ''){ 
   this.setState( 
     { 
        name: 'David', 
        age: 25, 
        metadata: {nationality: 'India', gender: 'male'} 
     } 
  }) 
} 

Examples of Using React setState()

Example 1:  Using react setState() with a button. 

import React, { Component } from "react"; 
import "./styles.css"; 
class App extends React.Component { 
  constructor() { 
    super(); 
    this.state = { 
      count: 0 
    }; 
    this.increase = this.increase.bind(this); 
    this.decrease = this.decrease.bind(this); 
  } 
  increase() { 
    this.setState({ count: this.state.count + 1 }); 
  } 
  decrease() { 
    if (this.state.count == 0) return; 
    this.setState({ count: this.state.count - 1 }); 
  } 
  render() { 
    return ( 
      <div style={{ margin: "50px" }}> 
        <h3>Counter App using Class Component : </h3> 
        <h2> {this.state.count}</h2> 
        <button onClick={this.increase}> Increase</button> 
        <button onClick={this.decrease}> decrease</button> 
      </div> 
    ); 
  } 
} 
export default App; 

By running the above code, you will get the output below: 

Example 2:  Using react setState() function with inputs. 

import React, { Component } from "react"; 
import "./styles.css"; 
class App extends Component { 
  constructor(prop) { 
    super(prop); 
    this.state = { name: "Michael" }; 
  } 
 
 
  changeTitle = (e) => { 
    this.setState({ name: e.target.value }); 
  }; 
 
 
  render() { 
    return ( 
      <div className="App"> 
        <h4>{this.state.name}</h4> 
        <p className="App-intro"> 
          Type here to change name. 
          <input type="text" onChange={this.changeTitle} /> 
        </p> 
      </div> 
    ); 
  } 
} 
export default App; 
 

The above codes produce the result below:

Example 3: Using react setState() with arrays.  

import React, { Component } from "react"; 
import "./styles.css"; 
class App extends Component { 
  constructor(props) { 
    super(props); 
    // Set initial state 
    this.state = { 
      courses: [ 
        "React JS", 
        "Node JS", 
        "Angular", 
        "Vue", 
        "React Native", 
        "NextJs", 
        "Blockchain" 
      ], 
      selected: [] 
    }; 
    this.clearSelected = this.clearSelected.bind(this) 
  } 
addToCourses(course) { 
    if(this.state.selected.includes(course)) return 
    this.setState({selected: [...this.state.selected, course]}) 
    alert(JSON.stringify(this.state.selected)); 
  } 
clearSelected() { 
    this.setState({selected: []}) 
    alert('Your selected course are now empty!') 
  } 
render() { 
    return ( 
      <div> 
        <h2>Choose Your Courses</h2> 
        <p>Click to select your courses</p> 
        <div className="courseList"> 
          {this.state.courses.map((course, i) => ( 
            <button key={i} onClick={() => this.addToCourses(course)}> 
              {course} 
            </button> 
          ))} 
        </div> 
<button onClick={this.clearSelected}>Clear Course!</button> 
      </div> 
    ); 
  } 
} 
export default App; 

 Here is the output: 

Using setState() with an Object as Updater

Using an object when updating a setState() is fairly simple, just like we have used it before. See the example below. 

// Using object as an updater 
stopCountDown() { 
  clearInterval(this.state.timer); 
  this.setState( 
    {  
      started: false, 
      timer: null, 
      time: 0 
    } 
  ); 
} 

Using setState() with a Function as Updater#

To use a function when updating a setState() we just have to return an object using another function. See this react setState example below.

// Using function as an updater 
startCountDown() { 
  const timer = setInterval(() => { 
    this.setState((preState, currState) => { 
      return { 
        time: preState.time + 1 
      } 
    }); 
  }, 1000); 
  this.setState({ started: true, timer }); 
} 

This can be seen in action using this timer app below: 

import React, { Component } from "react"; 
import "./styles.css"; 
class App extends Component { 
  constructor(props) { 
    super(props); 
    // Set initial state 
    this.state = { 
      time: 0, 
      started: false, 
      timer: null 
    }; 
    this.startCountDown = this.startCountDown.bind(this); 
    this.stopCountDown = this.stopCountDown.bind(this); 
  } 
 // Using function as an updater 
  startCountDown() { 
    const timer = setInterval(() => { 
      this.setState((preState, currState) => { 
        return { 
          time: preState.time + 1 
        } 
      }); 
    }, 1000); 
    this.setState({ started: true, timer }); 
  } 
 // Using object as an updater 
  stopCountDown() { 
    clearInterval(this.state.timer); 
    this.setState( 
      {  
        started: false, 
        timer: null, 
        time: 0 
      } 
    ); 
  } 
render() { 
    return ( 
      <div> 
        {!this.state.started ? ( 
          <h2>Start Timer!!!</h2> 
        ) : ( 
          <h2>{this.state.time}</h2> 
        )} 
        <div className="courseList"> 
          {this.state.started ? ( 
            <button onClick={this.stopCountDown}>Stop</button> 
          ) : ( 
            <button onClick={this.startCountDown}>Start</button> 
          )} 
        </div> 
      </div> 
    ); 
  } 
} 
export default App; 

This is what the output looks like: 

Calling setState() with an Object and a Callback Function#

This method comes in handy when performing asynchronous actions. For example, you can display a stoppage time for the countdown by calling another method. For using react setState object, see the example below. 

// Using object as an updater 
stopCountDown() { 
  clearInterval(this.state.timer); 
  this.setState( 
    {  
      started: false, 
      timer: null, 
      time: 0 
    }, 
    this.showEndtime(this.state.time) 
  ); 
} 
showEndtime(time) { 
  console.log(`Completed in ${time}sec!`); 
  alert(`Completed in ${time}sec!`); 
} 

Workings of `setState()`

There are about three steps under the hood a react setState() function uses for recalibrating a state variable. They include the state variable, the trigger, and the recompilation process.

  • State variable: Inputs from the user are entered here, for example, using an input element. 
  • Trigger: This is where state change events are emitted with new data. 
  • Recompilation Process: This is where the state variable is recalibrated and re-rendered with the updated value. 

Passing a Function to setState()

To pass a function as the react setState callback parameter, use the example below: 

handleChange = () => { 
  this.setState((prevState, currState) => ({ count: prevState.count + 1 })) 
} 
// or 
handleChange = () => { 
  this.setState((prevState, currState) => { 
    return {  
      count: prevState.count + 1  
    }; 
  }) 
} 
// or 
handleChange = () => { 
  this.setState(function(prevState, currState) { 
    return {  
      count: prevState.count + 1  
    }; 
  }) 
} 

And there you have it for mastering react setState function. 

Conclusion

We have come to the end of this tutorial; We hope you got a ton of value from the teaching. We have many more tutorials like this at KnowledgeHut. Also, check out KnowledgeHut React-native online course to speed up your software development career. 

For next steps, check out our blog posts about StrictMode in React

Till next time, enjoy! 

Frequently Asked Questions (FAQs)

1. What is this setState in React? 

In React, setState() is a class-based function that lets you modify a state variable within a given react component

2. How do you use setState in React?

You simply use it this way in any of your components this.setState({ stateVariable: newValue }). 

3. What is the difference between useState and setState?

While useState() is used in a functional-based react programming, setState() is used in a class-based programming.  

4. Is setState called on every render?

Yes, whenever a component renders or re-renders, its state variables are also called again. 

5. What is the second argument for setState?

The second argument of a setState() function is a callback function that is invoked after the state change.

6. Can we update the state without setState? 

Yes, but it is not recommended to change a state directly in react. It is considered bad because you can lose control of the state across components. 

Profile

Darlington Gospel

Blog Author

I am a Software Engineer skilled in JavaScript and Blockchain development. You can reach me on LinkedIn, Facebook, Github, or on my website.

Want to become a sought-after web developer?

Avail your free 1:1 mentorship session.

Select
Your Message (Optional)