Hey developer, welcome to part 3 of the React Basics series. In the last part we learned to setup a React project and looked at different types of React components. In this part as promised, we will be learning about states of a component.
State of a Component
As discussed in the earlier parts, React has the ability to render values of variables in an HTML template. This funtionality can be performed with the help of state of a component.
Let's take an example of our Cart
component.
src/components/Cart.jsx
import React from 'react';
export default class Cart extends React.Component {
render () {
return (
<h1>Hello, John</h1>
)
}
}
Localhost
Here, the name john is hard coded into the template(in the render function). But let's say this name John
should change when user interacts with the webapp. In order to do this we use the amazing power of Component State. We can define a variable which will hold this changing name and just simply call the variable in the template. Let us do that then.
Before that we need to understand the basic idea of how a constructor in classes work.
A constructor, in simple words, is a set of instructions to run as soon as a class is called. These instructions can be creating essential variables, calling APIs to store essential data for the application/component and many more. In our case we will initialize a state for our component. Let us analyze the below snippet.
src/components/Cart.jsx
import React from 'react';
export default class Cart extends React.Component {
constructor () {
this.state = {}
}
render () {
return (
<h1>Hello, John</h1>
)
}
}
You can see a constructor
keyword before the render method. This is how we define a constructor for a particular class in JavaScript. Inside the curly braces, we will define all the instructions to run at call. Here we can see a variable getting initialized this.state
which is assigned to...well..two curly braces 😕. This is actually how we define objects in JavaScript.
An object is a collection of key-value pairs, just like normal variables assigned to a value, in simple words it acts kind of like a collection of variables. So just like a variable, we can call a key in an object and get the assigned value. Now inside the this.state
object, we will be creating all the variables that we need to use in the template. Let us understand it with a code snippet.
src/components/Cart.jsx
import React from 'react';
export default class Cart extends React.Component {
constructor () {
this.state = {
first_name: "John"
}
}
render () {
return (
<h1>Hello, John</h1>
)
}
}
Here we created a key named first_name
and assigned a string value "John"
to it. Calling this key is pretty simple. As we learned, an object is a collection of key-value pairs, which basically means we should be storing this collection somewhere. So in this case we stored it in the variable this.state
. In order to call a key inside an object, we first have to refer to the variable holding the object followed by the name of the key you want to call. There are multiple ways to refer to a key in an object
- using the normal
object.<key_name>
method - using the indexing method.
// Object
this.state = {
first_name: "John"
}
// Method 1
this.state.first_name
// Method 2
this.state["first_name"]
For sometime we will be using method 1 and afterwards when the situation arises we will use method 2. Yes! These methods has to be used based on some situation. It's nothing complicated, we can do this!!!
Let us call the the first_name
key in our HTML template. We will have to use a weird syntax to do this. Let us analyze the below given snippet.
src/component/Cart.jsx
import React from "react";
export default class Cart extends React.Component {
constructor() {
super();
this.state = {
first_name: "John",
};
}
render() {
return <div>Hello, {this.state.first_name}</div>;
}
}
In the above code snippet, you can see how a variable is called inside the render function. You should use curly braces and write the name of the variable you want to call.
Feeling a little suspicious 🧐?
Check out line number 5. You see a super()
keyword. This is to setup all the functions and variables inherited from the React.Components
object. Have you wondered why is there a this
keyword before the state
variable. The this
keyword is used to access objects, variables and functions created in the class. Yes you directly cannot access the state
variable. Now if you check the browser, uhmmm...nothing has changed, lets try changing the value of the first_name
key to, let us say Sarah
.
src/component/Cart.jsx
import React from "react";
export default class Cart extends React.Component {
constructor() {
super();
this.state = {
first_name: "Sarah",
};
}
render() {
return <div>Hello, {this.state.first_name}</div>;
}
}
Localhost
Yeheheee 😉, look how it changed to the new value Sarah
. This is how React renders HTML dynamically. How about we take this a level up.
First 1 - let us add a button which will change the value of first_name
when clicked.
src/component/Cart.jsx
import React from "react";
export default class Cart extends React.Component {
constructor() {
super();
this.state = {
first_name: "Sarah",
};
}
render() {
return (
<>
<div>Hello, {this.state.first_name}</div>
<button>Change name</button>
</>
);
}
}
Step 2 - create a function which will change the name.
In a React component, we can create different functions for different tasks and call them inside the HTML template or call it normally also. Lets create a function to do this.
src/component/Cart.jsx
import React from "react";
export default class Cart extends React.Component {
constructor() {
super();
this.state = {
first_name: "Sarah",
};
}
change_name = () => {
this.setState({ first_name: "John" });
}
render() {
return (
<>
<div>Hello, {this.state.first_name}</div>
<button>Change name</button>
</>
);
}
}
Whoa whoa whoa what just happened 😵
Yeah, just added a function.
If you are familiar with JavaScript, you might wonder where is the function
keyword. Here is how react works, the "thing" you just saw is called an arrow function. If you want to read more about arrow function click here. If you have to access the variables of a class, you should be able to access the this
object. But when you create a function inside a class, you lose context to the this
object. Now if we bind or tie the this
object whenever we create a function inside a class, we will be able to access it inside the function. This is more like a React thing. There are multiple ways of binding the this
object. Below is a simple snippet showing that.
// Method 1
export default class App extends React.Component {
constructor (props) {
super(props);
this.state = {
first_name: "John"
}
this.change_name.bind(this);
}
change_name = function () {
// do something
}
render () {
return (
<h1>Hello, { this.state.first_name }</h1>
)
}
}
// Method 2
export default class App extends React.Component {
constructor (props) {
super(props);
this.state = {
first_name: "John"
}
}
change_name = () => {
// do something
}
render () {
return (
<h1>Hello, { this.state.first_name }</h1>
)
}
}
In method 1, we have used a normal syntax of creating a function. But in method 2, we have used the arrow function to create a function. While using method 1, you will have to manually bind the this
object to the function in the constructor
with the bind
function. But this is not the case for method 2, it automatically binds it to the function. We will be using method 2 in this series. Let us get back to our app.
src/component/Cart.jsx
import React from "react";
export default class Cart extends React.Component {
constructor() {
super();
this.state = {
first_name: "Sarah",
};
}
change_name = () => {
this.setState({ first_name: "John" });
}
render() {
return (
<>
<div>Hello, {this.state.first_name}</div>
<button>Change name</button>
</>
);
}
}
This is where we were!
Inside the change_name
function I we have added some code. In react we cannot directly reassign values of state keys. We have to use the setState
function to change the state. So you can just simply call the this.setState()
function and pass in an object with the key as the key you want to change the value of followed by the value as the new value.
Step 3 - Bind the change_name
function to the button
src/component/Cart.jsx
import React from "react";
export default class App extends React.Component {
constructor() {
super();
this.state = {
first_name: "Sarah",
};
}
change_name = () => {
this.setState({ first_name: "John" });
}
render() {
return (
<>
<div>Hello, {this.state.first_name}</div>
<button onClick={this.change_name}>Change name</button>
</>
);
}
}
We are going to use the onClick
attribute of <button>
element. The value of the attribute should be inside curly braces and keep in mind not to call the function with paranthesis, just end it with the name of the function only. If you add the paranthesis after the function name, it will be called immediately after the component is rendered.
It's time to check the browser
Localhost -- before
Localhost -- after
That's it for todayyyy!!
Drop your queries as comments.
Thank you for your time ☺️
Top comments (6)
Can I ask why you're still using class components? No criticism, just want to hear your take on it.
Hi Max, I got what you are saying. It is true that function based components are easy write and manage. But for the purpose of the course, I have found that teaching states with a class based component make a little more sense to beginners because the react hooks can confuse starters, me myself got confused how is this useState thingy working when I was a beginner 😅. The constructor method and implementing an object of all the variables you need seems a little more organised for me and it is solely my opinion. Also component life cycles will be easier for beginners to understand when compared to react hooks. I personally only use function based components with react hooks when I want a small component with not much of states and other logical things. But for bigger components I use class based components most of the time.
So there you go. Thanks for reading 😊
Thank you for your answer. I can see your reasoning here. I started using React around the time when hooks had recently been released, so I never even looked a class components. I agree that hooks were quite confusing in the beginning, but I'm glad I worked through it. The danger of following tutorials that use class components is that the people reading them might get even more confused when they continue learning, since most of the recent courses/tutorials are featuring hooks. I can see pros and cons for both. It could be a good thing to learn the old life cycle methods and state management if you're used to javascript since before. It might hurt less transitioning to useEffect and useState from there in some cases.
Thanks for spreading your knowledge :)
great content man...
Thank you so much Sarvesh, hope you learned something new.
yeah