Sign in
Log inSign up
ReactJS Basics: State in Class Component.

ReactJS Basics: State in Class Component.

Victory Ndukwu's photo
Victory Ndukwu
·Mar 7, 2021·

7 min read

In our previous article, we talked about props, and how they are used to pass data from parent components to child components, as a result, data passed to the child component is immutable from within the child. We might come across situations, where we want the data in a component to change in response to an event or over a period of time. This is where state comes in, component state is an object that stores the components properties, sometimes this properties change when an action occurs, for example, the subscribe button on YouTube's website, displays "subscribe" on the UI and when clicked, it displays "subscribed", the color also changes. The values that contains those properties are stored in the state of the subscribe button, then when a click event is fired, the value of that button state is changed.

Example: 1

Let us implement the subscribe button for clearer understanding.

import React, { Component } from "react";

//inline styling for the initial state of the button
const buttonStyle = {
  backgroundColor: "red",
  padding: "5px",
  color: "white",
  width: "150px",
  height: "50px",
  borderRadius: "5px",
  outline: "none",
  border: "none",
  transform: "translate(500px,200px)",
  cursor: "pointer",
  fontSize: "20px",
};

//inline styling for the toggled state of the button
const greyButton = {
  backgroundColor: "grey",
  padding: "5px",
  color: "white",
  width: "150px",
  height: "50px",
  borderRadius: "5px",
  outline: "none",
  border: "none",
  transform: "translate(500px,200px)",
  cursor: "pointer",
  fontSize: "20px",
};

//the Button component
export class SubscribeButton extends Component {
//since the component is a class, super() is required because we extend Reacts component class.

  constructor(props) {
    super(props);

//step 1: state is created inside the constructor,
// we use the this keyword since we are inside a Class

    this.state = {
//inside the state object, we set two state variables,
// text - this displays on the button
// val - serves as a value used to toggle the state, you'll understand why I did this as you go one
      text: "Subscribe",
      val: false,
    };
  }


//step 2: create a function that modifies the state.
//I am using ES6 arrow function syntax 
  modifyText = () => {
//the good folks on the React development team have provided us with a method, setState
//setState, accepts the state object, containing the new properties of the component
// DO NOT modify state outside of the setState method, React will not render the new state on the UI.
    this.setState({
//here the state variables are modified with their new properties.
      text: "Subscribed",
      val: true,
    });
  };

  render() {
    return (
      <button
//here I use the ternary operator to select which of the inline styles will be applied based on the second state variable I initialized earlier.
        style={this.state.val ? greyButton : buttonStyle}
//here we set an onClick event that triggers the modifyText we created in step 2 above.
// You will notice, the camel case convention used for 'onClick' event, this is how it is written in JSX, because a hyphen will be interpreted as the subtraction operator, since we are writing JSX and not HTML
        onClick={this.modifyText}>
        {this.state.text}
      </button>
    );
  }
}

export default SubscribeButton;

The initial state of the button:

Screenshot (6).png

The toggled state of the button, after being clicked:

Screenshot (7).png

Let us look at another example, to completely solidify the concept in my minds

Example 2

import React, { Component } from "react";

//inline styling to position the div
const position = {
  display: "flex",
  flexDirection: "column",
  justifyContent: "center",
  alignItems: "center",
};

//inline styling for the button 
  const Btn = {
  padding: "5px",
  width: "150px",
  height: "50px",
  cursor: "pointer",
  fontSize: "20px",
};

//inline styling for the text
const text = {
  fontSize: "20px",
};

export class Counter extends Component {
  constructor(props) {
    super(props);
//state initially set to zero
    this.state = {
      count: 0,
    };
  }

//increment function to update state
  increment = () => {
    this.setState({
      count: this.state.count + 1,
    });
  };

  render() {
    return (
      <div style={position}>
        <p style={text}>The Button was clicked {this.state.count} times</p>
        <button style={Btn} onClick={this.increment}>
          click me
        </button>
      </div>
    );
  }
}

export default Counter;

Below, the initial state of the counter: Screenshot (9).png

Below, the state of the counter, after I have clicked the button a couple times. Screenshot (10).png

setState

Calls to setState are asynchronous, meaning they don't execute sequentially, as a result of this, whenever you want to execute some code after the state has been set, do not place that code after the setState method. Instead pass it as a callback function as the second parameter of the setState method.

for instance:

  increment = () => {
    this.setState(
      {
        count: this.state.count + 1,
      },
//here setState method accepts a second parameter that logs to the console, the new state.
      () => {
        console.log(this.state.count);
      }
    );
  };

Try logging state to the console outside the setState method and observe the output.

The good folks at React have created an easier way to maintain state within a component, its called the useState Hook, we'll take a brief look at React Hooks, and dive deep into the useState Hook in the next article.

The code snippets are heavily commented, let me know if you prefer it this way.

Do leave questions, corrections if any, if there is something I didn't include please let me know.

Also let me know what React concepts you'd like me to explain next.