Damilola Adedoyin Ezekiel
31 Aug 2021
•
6 min read
In react, there are two ways to create components. Components can either be Class-based or Functional. As a newbie who just started learning React, understanding when to use either of these approaches might be a bit confusing. Although both the class-based component and the functional component give the same result depending on what you're trying to achieve, there are still some differences between these two, and in this article, we will be covering the major differences between the two components.
Class components (without destructuring)
When writing a class component, we can either extend it to React.Component
or we destructure it and extend it to the Component
alone. The render()
method is the only required method in a class component. Whenever the render method is called, it examines this. props
and this. state
and returns react elements(JSX), arrays and fragments, etc. It does not modify the component state.
import React from 'react';
class App extends React.Component {
render() {
return <h4>Hello World!</h4>;
}
}
Class components (with destructuring)
Destructuring is an ES6 feature and you can learn more about it here
import React, { Component } from 'react';
class App extends Component {
render() {
return <h4>Hello World!</h4>;
}
}
Functional components(using arrow functions)
Functional components can also be created using the ES6 arrow function feature. Arrow Functions are more simple and have a concise syntax for creating functions, which often makes them better to use than Function Expressions.
You can read more about it here
import React from "react";
const App = () => {
return <h1> Hello World! </h1>;
}
Functional Component(using function Expressions)
import React from "react";
function App() {
return <h1> Hello World! </h1>;
}
Props is short for properties and they are used as a means to communicate between the components, basically passing data from parent to child component. Passing props can be a bit confusing sometimes, let's see how props are being passed in both components.
Class-Based Component.
In a class-based component, we have to use this
keyword to access the prop or we can destructure it to get our value from the prop
import React, { Component } from "react";
class ParentComponent extends Component {
render() {
return (
<>
<ChildComponent name="sarah" age="12" hobby="cycling"/>
</>
);
}
}
class ChildComponent extends Component {
render() {
return (
<>
<h4>My name is {this.props.name}</h4>
<h4>I am {this.props.age} years old</h4>
<h4>I love {this.props.hobby}</h4>
</>
);
}
}
// we can also destructure it to look like this
class ChildComponent extends Component {
render() {
const { name,age,hobby } = this.props
return (
<>
<h4>My name is {name}</h4>
<h4>I am {age} years old</h4>
<h4>I love {hobby}</h4>
</>
);
}
}
Functional Component
In a functional component, the prop is being passed directly as an argument to the function and we can now access the prop by using prop.value
.
P.S: The value could be anything.
import React from "react";
const ParentComponent = () => {
return <ChildComponent name="sarah" age="12" hobby="cycling" />;
};
const ChildComponent = (props) => {
return (
<>
<h4>My name is {props.name}</h4>
<h4>I am {props.age} years old</h4>
<h4>I love {props.hobby}</h4>
</>
);
};
// with destructuring
const ChildComponent = (props) => {
const {name,age,hobby} = props
return (
<>
<h4>My name is {name}</h4>
<h4>I am {age} years old</h4>
<h4>I love {hobby}</h4>
</>
);
};
Before the release of React 16.8, handling and updating the state was only possible using a class-based component. But now, we can also handle state in functional components using the React hooks useState.
To understand how state works in react, we will build a counter application that increments and decrements whenever we have a call to action. This counter app will show us how to handle and update state in both class and functional components.
Class-Based Component
In the class-based component, we can access the value of the state by using this.state
inside JSX . You should not update the state directly instead you're to use setState to update the value of the state.
//this is wrong
this.state.name = " Hannah"
//do this instead
this.setState({ name: "Hannah" });
import React, { Component } from "react";
class App extends Component {
state = {
count: 0
};
addCount = () => {
this.setState({ count: this.state.count + 1 });
};
minusCount = () => {
if (this.state.count <= 0) {
this.setState({ count: this.state.count });
} else {
this.setState({ count: this.state.count - 1 });
}
};
render() {
return (
<div>
<button onClick={this.minusCount}>-</button>
<p>{this.state.count}</p>
<button onClick={this.addCount}>+</button>
</div>
);
}
}
Functional Component
We use useState to handle state in functional components. The useState hook gives us an array to work with and this array is made of two values: the state and the setter function and this setter function is what we use to update our state. The useState hook also takes in a value of what the default state is.
import React, { useState } from "react";
function App() {
const [count, setCount] = useState(0);
const addCount = () => {
setCount( count + 1 );
};
const minusCount = () => {
if (count <= 0) {
setCount(count);
} else {
setCount( count - 1 );
}
};
return (
<div className="App">
<button onClick={minusCount}>-</button>
<div>{count}</div>
<button onClick={addCount}>+</button>
</div>
);
};
In the example above, count
is our current state while setCount
is the setter function that updates our state. We then passed an onClick event to our button and it takes in a function that is minusCount
. The setter function which is setCount
is now used to decrement the value of our state inside the minusCount
function.
Note
The conditional statement in the minusCount function helps to stop the counter from counting negatively.
It is advisable to use functional components if your component will be a stateless one that is a component that does not have state.
Lifecycle methods are special methods built-in to React, used to operate on components throughout their duration in the DOM. For example, when the component mounts, renders, updates, or unmounts.
Class-based Component
In the class-based component, there are four main types of lifecycle methods. These are:
Render: we already know the render method is the most important lifecycle method. Every class component needs to contain a render method.
componentDidMount: it is called when an instance of a component is being created or inserted into the DOM. This is usually where we call our APIs, set timers, and also add event listeners.
componentDidUpdate: This is called when a component is being re-rendered as a result of changes to either its props or state. It runs when our component is being updated.
componentWillUnmount: This is called when a component is being removed from the DOM.
import React, { Component } from "react";
class Header extends Component {
constructor(props) {
super(props);
this.state = {favoritecolor: "red"};
}
componentDidMount() {
setTimeout(() => {
this.setState({favoritecolor: "yellow"})
}, 1000)
}
render() {
return (
<h1>My Favorite Color is {this.state.favoritecolor}</h1>
);
}
}
Functional Component
useEffect lets you perform side effects in a function. Since we've already gone through React class lifecycle methods, you can think of useEffect Hook as componentDidMount, componentDidUpdate, and componentWillUnmount combined.
This is the useEffect syntax :
useEffect ( () => {}, [] )
In the curly brackets, you can write the code that will be executed. The useEffect hook takes a second parameter, a “dependencies” array, that will only re-run the effect when the values within the array change across re-renders. This allows us to optimize how many times the effect is run. Although the dependency array at the end of the hook is optional however it will be needed more often.
There are three ways to express the dependency array :
a. With an empty array added at the end of the hook.
useEffect ( () => {
//do something here
}, [])
This works exactly like thecomponentDidMount
and this means that the hook will be run as soon as the component is inserted into the DOM.
b. Add the dependency array with a value.
This is quite similar to the example above, just that in this case a value is placed into the array and what this means is the hook will only be re-rendered as soon as the value changes. This is equal to how componentDidUpdate
works.
useEffect ( () => {
//do something here
}, [value])
c. Without adding the dependency array.
You can also completely leave out the dependency array. This way, the useEffect hook runs anytime the component is updated and right after the initial render. This is the difference compared to the componentDidUpdate lifecycle method because it also runs after the initial render. This way it would be equal to a componentDidMount and componentDidUpdate method combined.
The return statement we are adding to our useEffect is actually equal to a componentWillUnmount method.
useEffect(() => {
const timer = setTimeout(() => {
// do something here
}, 2000)
return () => {
// Cleanup work goes in here
clearTimeout(timer)
}
})
If you write a return statement like the above in a useEffect, it will do the same as a componentWillUnmount method. As you can see, there is a lot to the useEffect hook. You can also create your own custom hooks with it.
Using either of class-based or function approach comes with its own pros and cons however, I want you to take note of the following:
Functional components are easy to write and it also makes our code cleaner and more readable whereas the this
keyword in-class component can be confusing most times. However, this is not a debate to choose one over another. The majority of React codebases are still heavily dependent on the Class component and React has said that it will not stop supporting class components in the next foreseeable future. But it is advisable to start embracing functional components as hooks are taking over modern React.
Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ
108 E 16th Street, New York, NY 10003
Join over 111,000 others and get access to exclusive content, job opportunities and more!