A Comprehensive Guide To React Hooks For Beginners

Victoria Oluwaferanmi
12 min readMar 26, 2023

--

As someone new to React, it can be overwhelming to figure out how to use various tools. Despite becoming comfortable with a couple of hooks like useState and useEffect , it still took me a while to grasp the usage of other React hooks. Perhaps you’re also unfamiliar with how to use React hooks, this article will assist you in comprehending the concept more quickly.

Prerequisites

Before we dive into React Hooks, it’s important to have a basic understanding of React components and JSX syntax. If you’re not familiar with these concepts, it might be helpful to take a beginner-level course or tutorial before continuing.

It’s also helpful to have a basic understanding of JavaScript, particularly the ES6 syntax and concepts such as arrow functions, classes, and destructuring.

What are React Hooks?

If I had to describe React hooks, I would say they handle various tasks within components such as managing state, global state, side effects, and component functionalities. A state is used to store values that may change from their initial value and can hold different data types such as integers, booleans, arrays, objects, and more. When the state of a component changes, React automatically re-renders the component and updates the user interface to reflect the new state.

Hooks enable developers to reuse stateful logic across different components, resulting in more concise and reusable code. Overall, React Hooks make it easier for developers to build and maintain scalable and flexible React applications.

There are several types of Hooks, each serving a different purpose, and they provide a way to reuse stateful logic between components without the need for inheritance.

Types of React Hooks

  1. UseState —State
  2. UseEffect — Side Effects
  3. Use Context — Context API
  4. Use Reducer — Reducers
  5. UseRef
  6. Use Memo
  7. Use CallBack
  8. Custom Hooks — customized

The UseState Hook

The useState Hook is used to manage the state in functional components. It takes an initial state value as a parameter and returns an array with two values: the current state value and a function to update the state.

Example of how to use useState to manage a counter:

//import usestate from react

import React, { useState } from 'react';

function Counter() {

// count is the intial state, useState holds the initial value
// setCount is the updated state that holds the updated value

const [count, setCount] = useState(0);

function handleIncrement() {
setCount(count + 1);
}

return (
<div>
<p>Count: {count}</p>
<button onClick={handleIncrement}>Increment</button>
</div>
);
}

In this example, we use the useState Hook to manage the count state. We define the initial state value as 0 and use the setCount function to update the state when the button is clicked.

The UseEffect Hook

The useEffect Hook is used to perform side effects in functional components. Side effects can include fetching data from an API, manipulating the DOM. The useEffect Hook takes a function as a parameter and executes it after the component has rendered i.e useEffect is called after every render.

To conditionally run an effect, we specify a second parameter to useEffect. The second parameter is the array of values that the effect depends on.

Example of how to use useEffect to update DOM(title):The document title is updated as the useState value updates(number) i.e clicking on the IncreaseNumber button also updates the DOM element(title)

// import useEffect from 'react'
//The useState handles the state (number)
// The effect depends on the state value(number), we passed this as the second parameter

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

const UseEffect = () => {
const [number, setNumber] = useState(0);

useEffect(() => {
document.title = `You clicked ${number} times`;
}, [number]);
return (
<div>
<button
onClick={() => {
setNumber(number + 1);
}}
>
IncreaseNumber
</button>
</div>
);
};

export default UseEffect;

In this example, we use useState Hook to handle the number state. And useEffect to update the DOM element , this renders whenever the number state updates i.e it rendering depends on the state(number), this will be the second parameter ,the array value.

Using useEffect to fetch API data using JSON placeholder

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

function DataFetcher() {
const [data, setData] = useState([]);

useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(response => response.json())
.then(data => setData(data));
}, []);

return (
<div>
<ul>
{data.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
</div>
);
}

The UseContext Hook

To understand the usage of UseContext well, we consider a React App that have many components i.e components and in components. If these components then needs to access the same data across the application, we make use of useContext hook for easy consumption of the data. This provides a way to pass data through the component tree without having to pass it down manually on every level.

Steps in Creating Context

Step 1 — Create Context in App.js

export const UserContext = React.createContext();

Step2 — Provide context with a value to be available. The child/children component must be enclosed in the provider, for the value to be available.

<MyContext.Provider value="Victoria">
<MyComponent />
</MyContext.Provider>

Step3 — We then use the useContext hook: Used in Mycomponent.js to consume the value.

(i) Import useContext

(ii) Import the UserContext from App.js

(iii) Call the useContext function. It takes the context as an argument and returns the current value of the context.

import React, { useContext } from "react";

import {UserContext} from ./App

const MyComponent=() => {

const username = useContext (UserContext);

return (
<div>
{username}
</div>
);
}

When the MyComponent component is rendered, it will display the value "Victoria", which was passed down through the context from the App component. If we had multiple components that needed access to the same data, we could pass the value down through the context once and then have all the components consume it using the useContext hook.

The useReducer Hook

useReducer is a hook used for state management , more structured and predictable way than using the useState . This hook works in comparism the reduce() method in JavaScript, both involve reducing an array of values to a single value/ a pair of values. The useReducer hook returns a pair of values using array distructuring syntax, similar to useState .

The useReducer hook takes in two arguments: a reducer function and an initial state. The reducer function is responsible for handling state updates and returning a new state. It takes in two arguments: the current state and an action object that describes what kind of update needs to be performed.

useReducer(reducer, initialState)

newState= reducer(currentState, action)

The useReducer hook returns a pair (array) of values: the current state and a dispatch function. The dispatch function is used to trigger state updates and takes in an action object as its argument. When the dispatch function is called, React will call the reducer function with the current state and the action object, and then use the return value as the new state .dispatch allows us to execute a code corresponding to a particular action.

useReducer= const [currentState, dispatch]
//Recall useReducer takes two arguments

const [currentState, dispatch] = useReducer(reducer, initialState)

Now, we want to see how we can use useReducer hook to create a counter App.

Step 1 — Import useReducer from react

Step 2 — Defining the initial state and reducer function

Step 3 — Get value to display and call the useReducer function. Dispatch allows us to execute a code corresponding to a particular action.

Below is what the code look like following the steps:

//Import useReducers from React
import React, { useReducer } from "react";

// Define the initial state
const initialState = 0;

// defining reducer function
const reducer = (state, action) => {
switch (action) {
case "increment":
return state + 1;
case "decrement":
return state - 1;
case "reset":
return initialState;

default:
return state;
}
};

const UseReducer = () => {
// call the useReducer function
const [count, dispatch] = useReducer(reducer, initialState);

return (
// display the counter app, using dispatch to execute the action.
<div>
<div>{count}</div>

<button
type="button"
onClick={() => {
dispatch("decrement");
}}
>
Decrement
</button>
<button
type="button"
onClick={() => {
dispatch("reset");
}}
>
Reset
</button>
<button
type="button"
onClick={() => {
dispatch("increment");
}}
>
Increment
</button>
</div>
);
};

export default UseReducer;

In this example, we define a reducer function that takes in the current state and an action object. The action object has a type property that describes what kind of update needs to be performed. In this case, we’re defining three actions: increment, decrement and reset, which will increase , decrease and reset the count respectively.

We then define a component that uses the useReducer hook to manage the state of our count variable. We pass in the reducer function and the initial state declared (initialState=0) as arguments to the useReducer hook.

The Counter component then returns a JSX template that displays the current count and three buttons that use the dispatch function to trigger state updates. When the dispatch function is called with an action object, React will call our reducer function with the current state and the action object and use the return value as the new state.

Other ways to use useReducer hook in your application includes:

  1. Using UseReducer to maintain both state and action as objects
  2. We can use UseReducer and useContext for global state management
  3. Fetching Data using useReducer Hook.

I have all these examples in my GitHub repo that will be attached to the end of this article.

The useRef Hook

The useRef hook makes it possible to access DOM elements directly or to store mutable values that persist across renders(within effect). The useRef hook takes an initial value as its argument and returns a mutable ref object with a current property.

This code example demonstrates how to use the useRef hook in conjunction with the useEffect hook to focus an input element when a component is mounted.

import React, { useEffect, useRef } from "react";

const UseRefHook = () => {
const inputRef = useRef(null);

useEffect(() => {
//focus the input element
inputRef.current.focus();
}, []);

return (
<div>
<p>Using useRef for input focus</p>
<input ref={inputRef} type="text" />
</div>
);
};

export default UseRefHook;

In this example, we define a functional component called UseRefHook. Inside the component, we create a ref using the useRef hook and assign it to the inputRef variable. We then use the useEffect hook to call a function that focuses on the input element using the current property of the inputRef object. The second argument to the useEffect hook is an empty array [], which ensures that the effect runs only once, when the component mounts.

Finally, we return some JSX that includes a paragraph element and an input element that uses the inputRef reference.

By using useRef in conjunction with useEffect, we can ensure that the input element is focused when the component is first mounted. This can be particularly useful in cases where the input element is a crucial part of the user experience, such as in a search box or a login form.

UseMemo and UseCallback hooks

useMemo and useCallback are two hooks in React that are used for performance optimization. Both of these hooks are used to memoize or cache the results of an expensive computation, so that the computation does not need to be repeated every time a component re-renders. However, they are used in slightly different contexts.

The useMemo hook is used to memoize the result of a function call. It takes two arguments - a function and an array of dependencies. The function is the expensive computation that we want to memoize, and the dependencies are the values that the function depends on. React will re-run the function and recompute the result only when any of the dependencies change.

import React, { useState, useMemo } from "react";

const MemoHook = () => {
const [counterOne, setCounterOne] = useState(0);
const [counterTwo, setCounterTwo] = useState(0);

const IncrementOne = () => {
setCounterOne(counterOne + 1);
};
const IncrementTwo = () => {
setCounterTwo(counterTwo + 1);
};

const Even = useMemo(() => {
let i = 0;
while (i < 2000000) i++;
return counterOne % 2 === 0;
}, [counterOne]);

return (
<div>
<div>
<h1>Using MemoHook</h1>
<button onClick={IncrementOne}> Counter-One {counterOne}-</button>
<span>{Even() ? "Even" : "odd"}</span>
</div>
<div>
{" "}
<button onClick={IncrementTwo}>Count-Two {counterTwo}</button>
</div>
</div>
);
};

export default MemoHook;

In the given code, useMemo is used to memoize the result of a function that checks if the counterOne value is even or odd. The function is called Even and it's defined inside the component. The function uses a loop to delay the execution, which simulates an expensive computation.

The second argument of useMemo is an array of dependencies, which tells React to recompute the memoized value whenever any of the dependencies change. In this case, the only dependency is counterOne, so the memoized value will only be recomputed when counterOne changes.

The memoized value is then used in the JSX to display “Even” or “odd” depending on the value of counterOne. This means that the expensive computation of Even only happens when counterOne changes, and not on every render of the component.

The useCallback will return a memoized version of the callback version that only changes if one of the dependencies has changed.

To catch function — useCallback

To catch result — useMemo

The Custom Hooks

Custom hook simply means a customized way of creating reusable logic. A custom hook is a function that uses one or more built-in React hooks (such as useState, useEffect, useContext, etc.) and returns stateful data and functions that can be used by other components.

How To Create and use a Custom Hook

Creating a Custom Hook

Step 1 — Identify the reusable logic: Determine what code can be extracted into a separate function to make it reusable across components.

Step 2 — Create a new function : The function name must start with use (keyword used to represent an hook) that will hold the reusable logic. This function should use one or more built-in React hooks, this is the custom hook.

Step 3 — Define the hook’s return value: Determine what data or functions should be returned from the hook.

Step 4 — Export the custom hook: Export the new function as a custom hook.

Example: Counter App CustomHook

import { useState } from "react";
//using useCounter hook instead of repeating the same code for components
//reusable logic
//Hook named useCounter

const useCounter = (initialCount = 0, value) => {
const [count, setCount] = useState(initialCount);

const decrement = () => {
setCount((prevCount) => prevCount - value);
};
const increment = () => {
setCount((prevCount) => prevCount + value);
};
const reset = () => {
setCount(0);
};

//we return an array of values: count, inc, dec, and reset
return [count, increment, decrement, reset];
};
//export useCustom
export default useCounter;

Using a custom hook

  1. Import the custom hook: Import the custom hook into the component where it will be used.
  2. Call the custom hook: Call the custom hook inside the component. This will return the data or functions that were defined in the hook.
  3. Use the returned values: Use the returned data or functions in the component as needed.
import React from "react";
// import the custom hook

import useCounter from "./useCounter";

const CustomHooksComponent1 = () => {
//use the custom hook and its logics in the component

const [count, increment, decrement, reset] = useCounter(10, 2);
return (
<div>
CustomHooksComponent1
<div>
<p>CustomHook1- {count}</p>
<button onClick={decrement}>Decrement</button>
<button onClick={increment}>Increment</button>
<button onClick={reset}>Reset</button>
</div>
</div>
);
};

export default CustomHooksComponent1;

The useCounter hook takes two arguments, an initial count value of 10 and a step value of 2, and returns an array containing the current count value, a function to increment the count, a function to decrement the count, and a function to reset the count to its initial value.

The component then uses these values to render a simple counter UI with three buttons to increment, decrement, and reset the count value. When the user clicks on one of these buttons, the corresponding function from the useCounter hook is called to update the count state and re-render the component with the new count value.

Overall, this component demonstrates how a custom hook can be used to encapsulate complex state logic and make it reusable across multiple components. By using the useCounter hook, the CustomHooksComponent1 component can manage its own count state without having to write any custom state management code.

Conclusion

React hooks are a powerful and flexible feature that allows developers to write more modular and reusable code in their React applications. Whether you need to manage component state, fetch data from an API, or interact with the browser DOM, there is likely a hook that can help you accomplish your task more efficiently.

While it can take some time to get comfortable with the different types of hooks and their various use cases, the benefits of using hooks can be substantial, including improved code readability, easier debugging, and faster development times.

Final Piece

If you’re interested in learning more about React hooks and how they work in practice, you’re in luck! I’ve put together a comprehensive Github repository that includes code examples for all the most important React hooks to help you understand how they work.

It’s such a long one right? Yea! we just covered all the React Hooks.

Thank you for taking the time to read this article. I hope that it has given you a better understanding of how to use React hooks effectively in your own projects.

https://github.com/VictoriaOluwaferanmi/ReactHooks.git

--

--

Victoria Oluwaferanmi
Victoria Oluwaferanmi

No responses yet