Class-Based Components in React

Utilizing State and Lifecycle Methods

Erik Huang
6 min readMar 10, 2021

After spending more than half a year studying the intricacies and weirder parts of vanilla Javascript, making the transition over to React felt monumental. In some ways, it was like the moment my Magikarp finally evolved into a Gyarados as a kid playing Pokemon. In others, it was like reading “The Life-changing Magic of Tidying Up” by Marie Kondo and finally tackling the mess in my room (or code) using logical, pre-established methods and implementing them.

In Marie Kondo’s book, she explains that you should tidy your home by category, not location. This means that instead of cleaning out the garage before moving onto the bedroom or cleaning out your shelves before moving onto your desk, you should organize your tidying by similar items, such as putting away all the clothes you own in the house and then moving on to your book collection.

Building an application in React follows a very similar process. Instead of writing a HTML file with all the elements on your page, manipulating the DOM in a separate JS file for every element, and finally attaching a CSS file to style everything in your project, React allows you to organize your HTML, CSS, and JS categorically based on components.

Class Components vs Functional Components

Components are the main building blocks of React, and represent re-usable sections of your application. They can serve two primary purposes: to produce HTML that can be displayed to the user (through JSX), and to handle input and feedback coming from the user. A component can be defined as either a Javascript class or function.

Up until very recently, class components had much more functionality than their counterparts. Functional components could only display content to the user, while class components, in addition to that, could also utilize the ‘state’ system to update content and the Lifecycle method to run code at very specific points in time.

Although recent updates have allowed functional components to now have many of the same qualities as class components using something called the Hooks system, in this blog, we will turn our attention to the attributes that make up a class-based component in React.

Subclasses of React.Component require a render function

Rules of Class Components

In order to properly create and utilize a class-based component in React, we must adhere to several rules:

  1. It must be a Javascript class.
  2. It must extend to React.Component (as a subclass).
  3. Inside the class, a render function must be defined that returns some JSX.

Let’s create a new class for a Clock component. We will use the JS class keyword to define our Clock and the extend keyword to designate it as a subclass of React.Component.

This takes care of the first two requirements, but we still need to define a render method inside our new class. The render method will most likely be called many many times within our application, and its primary purpose should be to return some JSX that can be interpreted for the user.

Any HTML classes must be defined as “className” in JSX.

We want to eventually return a div element that displays and updates the current time as it passes. However, in order to achieve that, we will first have to talk about two attributes that appear in class components: State and Lifecycle Methods.

What is State?

State can be a difficult topic to grasp when first learning React. Put simply, State is a Javascript object that contains data pertaining to a single component. In some ways, it can be very confusingly similar to the Props object.

According to the official React documentation:

While both hold information that influences the output of render, they are different in one important way: props get passed to the component (similar to function parameters) whereas state is managed within the component (similar to variables declared within a function).

In other words, we define and update values in the state object within the context of our class component. State must be initialized whenever a component is created. Any updates we make to the values within state are almost instantly re-rendered for us.

Initializing State through Constructors

We can initialize the state object inside our Clock component using a constructor method. It isn’t unusual to initially pass in null or empty values for our keys at first. By accessing the value stored within this.state, we can pass that into our render function as well wrapped around curly braces.

The contructor function inherits from the React.Component parent class and initializes values in state.

However, we still need a way to get the current time AND update it correctly on the screen. This is where component lifecycle methods come in.

What is a Component Lifecycle?

Within an application, a component can be created, appended to the DOM, altered(re-rendered), and finally removed at specific points in the program. Lifecycle methods are pre-designated functions within our class component that can be optionally defined and automatically called by React at certain times during the component’s “lifecycle”. The following image from freecodecamp.org illustrates the various potential phases that could occur within a class component.

The constructor function in Clock would be an example of the initialization process during its lifecycle, while the render function, although called at initialization, will also be repeatedly implemented during each subsequent phase. Updating the value of time inside our initial state should fall to the next two phases: mounting and updating.

Getting the Time inside componentDidMount()

In React, we have access to a function called componentDidMount() that allows us to fetch the current time for our Clock. Since mounting occurs after our initial content has already appeared on the screen, it is a good place to do data-loading executions.

What does that mean? Well, in order to display the time in render, first we need to make an asynchronous request to the JS Date object that will return the current time. Since this operation could take a little while, we should put it inside componentDidMount() and use setInterval() to update it every second.

How can we assign the value of new Date().toLocaleTimeString() to our state object?

However, we are missing one last step. There has to be some way we can assign the value from new Date().toLocaleTimeString() and constantly update this.state.time with it. We have one more method that can help to assign new values to state: setState().

Updating State with setState()

This is very important to remember: except for initialization, we can ONLY change values within state using the setState() function. It is never a good idea to try it any other way. Using this specialized function, all we have to do is pass in an object containing the key(s) in state that we want to alter along with their new value(s).

If we use this method to alter our Date string, it is a simple matter of just passing our call to new Date().toLocaleTimeString as an argument like so:

setState() must accept an object containing new values for key(s) in the state object.

Now our componentDidMount() function is complete! We simply place this inside our Clock component, and together with our reference to this.state.time inside the render function, our Clock app is now working!

As a final refactor, we can condense our constructor function into one line and change its initial value to the new Date().toLocaleTimeString() value. Since React has access to Babel, a Javascript compiler that converts the JSX we write into functional Javascript code, we can simply initialize our state with the line state = { time: new Date().toLocaleTimeString() }.

Conclusion

As mentioned in the beginning of this article, recent updates to React have made it so we can now perform many of these same actions with functional components as well. Using the React Hooks system and Redux effectively are indispensable skills for any modern React developer, but there is a very good reason to learn class components first: it makes the process of mastering both ways that much easier.

With a solid foundation in class-based components, not only will you acquire the confidence to tackle React hooks, you will also be able to easily analyze the code of many established businesses that utilize hundreds of class components on their website. Since both class and functional components will be used regularly for the foreseeable future, now is the time to master these concepts!

--

--

Erik Huang

I am currently a student in the software engineering program at Flatiron school