Understanding the React Hooks

Mohsin Raza
GDSC, IIIT Allahabad
7 min readMar 24, 2022
React Hotu oks

In this article, we will learn how to use react hooks. As we know with the release of React 16.8, React hooks are available and can be used.

Flow of Article :

What are React Hooks?

Why should we use hooks over React classes?

Different Type of Hooks

UseState

UseEffect

Custom React Hooks

Conclusion

Let’s start :

What are React Hooks?

With the help of React Hooks, we can use state and other React features without writing a class. We can also make custom hooks to share reusable stateful logic between components. For example, If we write a function component, and then we want to add some state to it, previously we do this by converting it to a class. But, now we can do it by using a Hook inside the existing function component.

Let’s see this with an example:-

1) First of all, configure a React development environment

Open a folder and open that folder with VS code(Any Code editor ). Now run this command in the terminal:-

npx create-react-app react-hookscd react-hooks

2) Now make a file of name Example.js in src folder:-

3) Write this code in Example.js File :-

import React, { useState } from "react";export default function Example() {const [count, setCount] = useState(0);return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);}

4) Now import and call this component in App.js :-

import './App.css';import Example from './Example';function App() {return (<div className="App"><Example/></div>);}export default App;

This example renders a counter. When you click the button, it increments the value

Here, useState is a Hook(we’ll talk about it later). We call it inside a function component to add some local state to it. React will preserve this state between re-renders. useState returns a pair: the current state value and a function that lets you update it. You can call this function from an event handler or somewhere else.

Why should we use hooks over React classes?

1. We don’t have to refactor a functional component into a class component

There are times when a React component starts with a functional component, evolves into a Class component with having a state. Changing from a functional component to a class component requires a little bit of refactoring. But with React Hooks, since functional components have the capability of tapping into the state, the refactoring effort will be minimal.

2. No ‘this’ anymore

If you are familiar with JavaScript, you know that ‘this’ in JavaScript doesn’t work exactly like in other languages. When it comes to React Hooks, you don’t have to worry about ‘this’ at all.

3. We can share stateful logic between components

Previously, it was hard to share stateful logic between components. Consider two components where we had to fetch, sort, and display data from two different data sources, It was hard to share the logic because these components had different sources and states.

Although we can use render props and higher-order components to solve such cases, it will also cause its own problems as we have to restructure our components, which will eventually make it harder to follow.

But now with the help of React Hooks, we can easily share stateful logic between components.

Different Type of Hooks

There are many hooks as follows :

useState()

useEffect()

useContext()

useReducer()

useMemo()

useCallback()

useImperativeHandle()

useDebugValue()

useRef()

useLayoutEffect()

For now , we will only look at useState() and useEffect().

useState()

Earlier there was this.setState which was used to change the state.

Consider the following example where this.setState is used:-

import React, { Component } from "react";export default class Button extends Component {
constructor() {
super();
this.state = { buttonText: "Click me" };
this.handleClick = this.handleClick.bind(this);
}
handleClick() {
this.setState(() => {
return { buttonText: "Clicked!" };
});
}
render() {
const { buttonText } = this.state;
return <button onClick={this.hadleClick}>{buttonText}</button>;
}
}

As seen from the above code, while clicking the button the component’s internal state gets changed by this.setState. Then the text’s button in turn reacts to this change and receives the updated text.

But now in place of this.setState we have a hook called useState for managing the internal state.

Let’s see this example with hooks -

First, let’s import useState in our file:

import React, { useState } from "react";

After importing we have to destructure two values from useState:

const [buttonText, setButtonText] = useState("Click me")

we can use any name for destructuring, it doesn’t matter in React. But it is advised to use meaningful variables.

useState takes an argument to pass in it, which is called the initial value. This is the data that will be changed afterward.

Now, the previous example of button component can be written in useState hook as follows :

import React, { useState } from "react";function Button() {
const [buttonText, setButtonText] = useState("Click me");
return (
<button onClick={() => setButtonText("Clicked!")}>
{buttonText}
</button>
);
}
export default Button;

useEffect()

useEffect is mainly used to fetch data in React.

When there were no hooks, we had to use componentDidMount for fetching data in class-based components.

class dataFetch extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
componentDidMount() {
document.title = `You clicked ${this.state.count} times`;
}
componentDidUpdate() {
document.title = `You clicked ${this.state.count} times`;
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}

In React class component, for causing side effects only render method is not enough. As it will update the changes too early but we want the changes to be reflected after React has updated the DOM.

This is why we have to put the side effects into componentDidMount and componentDidUpdate.

But nowadays we use useEffect() hook to fetch data because it is easily understandable and simple.

According to the documentation “useEffect serves the same purpose as componentDidMount, componentDidUpdate and componentWillUnmount in React classes, but unified into a single API” and also instead of calling this.setState we will use useState .

Let’s see this example with hooks :

Import useEffect and useState in our file.

import React, { useState, useEffect } from 'react';

Now using useEffect in our code

function dataFetch() {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `You clicked ${count} times`;
});
}

First We will declare the count state variable. Then we will use useEffect and pass an arrow function inside it which is an effect that will be subjected to change. Now we can read the counts in this effect. When React renders our component, it will remember the effect we used, and then run our effect after updating the DOM. This happens for every render, including the first one.

Above code with the help of React hooks :

import React, { useState, useEffect } from 'react';
function Example() {
const [count, setCount] = useState(0);
useEffect(() => {document.title = `You clicked ${count} times`; });
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

useEffect hook tells the React that components need to do something after render. React will remember that function, and will call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API. It runs both after the first render and after every update.

Custom React Hooks

Instead of render props, we can encapsulate our logic in a React hook and then import that hook whenever we feel the need. In this example, we can create a custom hook for fetching data.

//in useFetch.js file
import { useState, useEffect } from "react";
export default function useFetch(url) {
const [data, setData] = useState([]);
useEffect(() => {
fetch(url)
.then(response => response.json())
.then(data => setData(data));
}, []);
return data;
}

Now, using this custom hook :

import React from "react";
import useFetch from "./useFetch";
export default function Datafetch(props) {
const data = useFetch("http://localhost:3000/data/");
return (
<div>
<ul>
{data.map(el => (
<li key={el.id}>{el.title}</li>
))}
</ul>
</div>
);
}

This is what makes hooks so appealing: finally, we have a nice, standardized, and clean way for encapsulating and sharing logic.

Conclusion

React Hooks are a nice addition to the library. React hooks make render props and HOCs almost obsolete and provide nicer ergonomics for sharing stateful logic.

React ships with a bunch of pre-defined hooks. The most important are useState and useEffect. useState makes it possible to use local state inside React components, without resorting to ES6 classes.

useEffect replaces componentDidmount, componentDidupdate, and componentWillUnmount with a unified API.

That’s it Guys, I hope you all enjoyed reading this blog and learned something new.

Thank you so much for reading this blog. Be Healthy, Be Safe, Do yoga.

--

--