In this post, we will look at functional components using React Hooks that were introduced in version 16 of React and why you should use them over class components. This post is suited to React developers who are familiar with classes and new React developers who are wondering which one to use.
According to the official documentation, Hooks brings into a functional component all the powers previously accessible in class components and made them available in functional components. With React Hooks, you can now use state and other features of React outside of the construct of a class:
import React, { useState } from 'react'; function Example() { // Declare a new state variable, which we'll call "count" const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}> Click me </button> </div> ); }
useState
is one of the Hooks available for use in a React functional component. Although Hooks were released last year, they shipped with some added advantages like having no breaking changes. This means that it is totally backward-compatible and it is optional to use, meaning you can choose to stick to classes if you want or you can try out Hooks.
With the introduction of Hooks, you can now do everything you would normally do in a class, inside a functional component. This is a game-changer because you have fewer concepts to learn and fewer lines of code to write too. Before last year, React developers already used classes so it may not be easy to leave something you have been using for a while for something new but since Hooks are optional, you can give it a try without any blowbacks.
React developers know that you cannot really escape using lifecycle methods if you use class components, componentDidMount
is one of the most popular ones. It runs after the first component render has been executed. To illustrate, let us create a class component to return a header about this LogRocket blog:
class NewComponent extends React.Component { componentDidMount() { console.log("The first render has executed!"); } render() { return <div> <h3>You are reading a LogRocket article</h3> </div>; } }
Now after this is run, you have to include the componentWillUnmount
lifecycle to destroy this one already mounted. Now thanks to React Hooks, you can get this same lifecycle method behavior inside a functional component, I think this is revolutionary:
const FunComponent = () => { React.useEffect(() => { console.log("The first render has executed!"); }, []); return <div> <h3>You are reading a LogRocket article</h3> </div>; };
This code block above uses a React Hook called UseEffect
and with the empty array second argument it returns the same output with the class component we defined above.
This is probably the next question you asked after seeing that Hooks can act like lifecycle methods in functional components, and yes you can now handle state in a functional component thanks to Hooks. To implement state in a simple clicker class used to count down from a hundred, this is how most people might go about doing it:
class NewComponent extends React.Component { constructor(props) { super(props); this.state = { counter: 100 }; } render() { return ( <> <p>counter: {this.state.counter} counts left</p> <button onClick={() => this.setState({ counter: this.state.counter - 1 })}> Click </button> <> ); } }
Now you know you must have super props for stateful logic, now to achieve this with a functional component, this is what it looks like:
const FunComponent = () => { const [counter, setCounter] = React.useState(100); return ( <> <p>{counter} more counts to go!</p> <button onClick={() => setCounter(counter - 1)}>Click</button> <> ); };
The useState
Hook is used to handle stateful logic in functional components and the syntax is really as easy as it seems. Here are a few other reasons you may want to write functional components instead of classes.
So with a functional component, you write fewer lines of code on average compared to the equivalent in a class component. Here is a small example where we return a div tag that contains a small heading with a class component:
import React, { Component } from "react"; class NewComponent extends Component { render() { return <div> <h3>You are reading a LogRocket article</h3> </div>; } }
For a functional component it would look like this:
import React from "react"; const FunComponent = () => { return <div> <h3>You are reading a LogRocket article</h3> </div>; };
In the example above you can see that there are fewer concepts to learn or understand in a functional component than in a class component. A functional component is a simple function that only returns JSX, while on the side of the class component, you have to understand the render method and how it is used to extend React.component
.
This is a well-debated point but even the React team confirms that the use of classes in JavaScript can be confusing sometimes for developers and even machines. One of the confusing things is using this
for things like passing properties and how it works in different languages. To illustrate, imagine you had a heading component with a title:
<Heading title="blog" />
Passing this title property has a very distinct syntax for both functional components and class components. For a class component, the code block will look like this:
class NewComponent extends React.Component { render() { const {title} = this.props; return <h3>You are reading a LogRocket {title}</h3>; } }
We had to bind it to this.props
to output “You are reading a LogRocket blog” on render, meanwhile, you do not have to bother about this while using a functional component to achieve the same results:
const FunComponent = ({ title }) => { return <h3>You are reading a LogRocket {title}</h3>; };
This post is an overview of React Hooks and reasons why you should use them in functional components instead of class components. If you would like to learn more about React Hooks, check out the official documentation and if you just want to learn how to refactor your app from classes to functional components with Hooks then check out this great article. I hope you find this helpful, happy hacking!
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowThe useReducer React Hook is a good alternative to tools like Redux, Recoil, or MobX.
Node.js v22.5.0 introduced a native SQLite module, which is is similar to what other JavaScript runtimes like Deno and Bun already have.
Understanding and supporting pinch, text, and browser zoom significantly enhances the user experience. Let’s explore a few ways to do so.
Playwright is a popular framework for automating and testing web applications across multiple browsers in JavaScript, Python, Java, and C#. […]
4 Replies to "Why you should adopt React Hooks instead of classes"
The first code block needs a newline before const, and the fourth says `counter: this.state.count – 1` but should say `counter: this.state.counter – 1`.
Thanks for the notes, we’ve updated the post
In the What are React Hooks? and the Fewer lines of code paragraphs you are importing React but never use it…
The obsession with not having to learn lifecycle methods is baffling honestly, it’s like people don’t want to learn their own craft. It’s too complicated? lmao are you kiddin me? The next gen of UI dev is going to be clueless to how anything nuanced is accomplished.