When writing this course, React was on version 17.0.2 and has evolved over the years, which means that the way we write components today looks nothing like the way they were in the beginning. Unfortunately, that means some codebases contain components written using other syntaxes. Time to get back in our time machine to take a look over the main stages in React’s evolution. 🚀
createClassWhen React became open source in 2013, components were created with React.createClass . To give you an example, a MyComponent component that receives a title prop would be written as:
React.createClass({
displayName: "MyComponent",
render() {
return (
<div>
<h1>{this.props.title}</h1>
</div>
)
}
})These days, though, this syntax is considered to be deprecated, and you won’t find it anywhere in React’s documentation.
However, you’re likely to stumble across class components.
With the addition of classes in ES 2015 (here is Mozilla’s documentation on classes), React wanted to align itself by creating class components. It was a time of major change. In this and the following chapters, we will go over their syntax, how to make API calls, and manage state and props in class components.
Learn about the syntax of class components in the screencast below. 👇
If you’d like to see the full code for this whole component, you can find it here, on the GitHub repository.
As you’ll have seen from the screencast above, class components have different syntax. We’re going to create a new EmailInput component and put it in the footer.
Start by declaring the component:
import { Component } from 'react'
class EmailInput extends Component {
constructor() {
}
render() {
return (
<div>
<input />
</div>
)
}
}
export default EmailInputYou declare your components with class and extends Component. If you’ve ever worked with classes, you’ll have already seen extends and constructor . It’s important to know that constructor (documentation here) is a method for creating and initializing an object when you’re using the keyword class.
What’s is render ?!
It's one of your component’s methods. In fact, it’s the only method that you are obliged to call in your component (so it needs to be there). For certain events, your component will have to re-render. Each time, this method will recalculate what is declared and display what is returned.
A new render will happen every time an update takes place:
When initializing the constructor .
Whenever a prop is updated.
For every change to state (more on this later).
render is not a feature of function components.
Note that render must return JSX (which will be in the return ). But if you have nothing to return in your render , you can also return null .
We’re now going to add a bit of style to the component that we’ve just created, creating a version for the darkMode and one for the lightMode . In a previous chapter, you learned that using context is much easier with hooks. Unfortunately, you can’t use hooks from class components. Therefore, you have to pass the theme as props.
But we don’t have any parameters in which we can get props, so how do we get them?
Don't worry, there’s a way to get your props in class components by using this.props throughout your component – whether it’s in the return ,render , or a method. Start by initializing them in the constructor , and then pass the initial state , even if you don’t need it for now (it keeps our linter happy).
Declare the following in your component:
class EmailInput extends Component {
constructor(props) {
super(props)
this.state = {
inputValue: '',
}
}
render() {
// Here we get theme by destructuring this.props
const { theme } = this.props
return (
<div>
<input />
</div>
)
}
}With this, you can apply a different style depending on your theme . You can find this style on P4C1-exercise.
Then what’s this ?
If you’re familiar with JavaScript, you’ll have come across this , which refers to the object it belongs to. If you need a reminder, you can see how to define a class in JavaScript in the chapter “Define objects and their attributes with classes” of the course Learn Programming With JavaScript.
Here, this refers to the component: it is the props and the state of EmailInput .
Careful, though – when you declare the methods (which are kind of functions) in your components, you need to pay attention to the bind .
The what? The "bind"?
To put it simply, you use bind to bind your methods to your class component: they need to be correctly bound to the this . You’ll understand better once you see the state . ✨
setStateLet’s now manage the value entered into the EmailInput with setState .
Isn’t setState more or less the same as useState ?
Not really. First of all, useState is a hook: it’s how you manage state for function components. setState is for class components. Although both functions deal with state, they do not work in the same way:
useState lets you declare your state variable, initialize its value, and get a function to update it.
setState only lets you update the state in your component. Remember, the initial state is declared in the constructor .
You have to go step by step to manage the state of the value entered into EmailInput . If you’re struggling to follow, all of the code you need is on the GitHub repository.
In the section just above, you initialized your state in the constructor with:
this.state = {
inputValue: '',
}You’re now able to declare a function to update the value of your state:
updateInputValue = (value) => {
this.setState({ inputValue: value })
}There is no need to have const = in front of your function. Usually, you’d have to initialize it, but given that you’re in a class , updateInputValue is a method of your EmailInput class.
Could we have put updateInputValue in the render ?
Yes, but everything within the render is run every time a prop or the state is updated. That means that your function would be declared again, which wouldn’t be very efficient, would it?
This method is called in onChange from input :
<input
onChange={(e) => this.updateInputValue(e.target.value)}
/>Here, every time a setState is run, it will trigger a new render in your component.
There are certain rules to follow for setState (the fact that setState is asynchronous, that state updates are merged, etc.). Learn these rules in React's documentation.
And just like you access props with this.props , you use this.state to access the current state.
Do the following to display the input:
render() {
return (
<div>
{this.state.inputValue}
<input
onChange={(e) => this.updateInputValue(e.target.value)}
/>
</div>
)
}thisUsually, when you declare a new function, you use the syntax function myFunction() . So why are we using an arrow function here?
To access your method in your class, you need to bind your function to your class. Arrow functions let you do this implicitly. Problem solved.
Without an arrow function, you’d have to do it explicitly like this: 👇
constructor(props) {
super(props)
this.updateInputValue = this.updateInputValue.bind(this)
this.state = {
inputValue: '',
}
}
updateInputValue (value) {
this.setState({ inputValue: value })
}this can be a bit tricky to grasp. That’s one of the reasons why React chose to promote function components, to make things easier at the learning stage. The Medium article “What is ‘this’ in React?” goes back over the key ideas.

It’s time to put everything you’ve just learned into practice. To do this, I’ve turned the Card component into a class component and created an EmptyList component that lets you signal to the user that the skills list is empty (if they have answered ‘no’ to all questions). Your task is to:
Recreate the favorites system, which adds "⭐️" around the name of the freelancer that we’ve clicked on in Card , sticking with a class component.
Transform the EmailInput component into a function component.
Transform the EmptyList component into a function component.
As usual, you’ll find the start of the exercise on the branch P4C1-begin, and the solution on P4C1-solution. Over to you! 🚀
Class components appeared at the same time as class in JavaScript.
A class component is declared withclass ComponentName extends Component .
render is called every time an update occurs.
State is updated with setState , to which you pass an object as a parameter.
Props and state are accessed with this.props and this.state .
In the next chapter, we’ll look into another essential aspect of class components: lifecycle methods. You’ll also learn how to call an API in a class component. See you there! 🚀