Mastering React Hooks: Everything you need to get started
Unlocking the Potential of React Hooks for Seamless State Management and Component Logic
Hello everyone! In this blog, I'll be dissecting the most common React hooks that are heavily utilized in React application development.
There are two types of components in React: state components and functional components. Initially, React didn't support lifecycle features like constructor()
, getDerivedStateFromProps()
, render()
, componentDidMount()
, etc. That's where hooks come in. Hooks allows us to seamlessly integrate with React features such as state management and lifecycle methods in functional components.
There are seven hooks in React: useState
, useEffect
, useCallback
, useMemo
, useRef
, useContext
, and useReducer
. Among these, useState
and useEffect
take center stage, accounting for approximately 90% of usage. Alongside these, we'll also explore useMemo
and useRef
, with a brief introduction to custom hooks. useCallback
would require a complete blog to itself.
Let's dive in.
1. useState
Hook
useState is the most common hook in React. As the name suggests, it handles state management in react.
In React, every component undergoes re-rendering upon state change.
Syntax:const [count, setCount] = useState(0);
In the above syntax:
count
represents our state variable.setCount
is the function employed for updating the variable.0
denotes the initial value for the variable.
Syntax for Updating State:setCount(1)
The useState hook accommodates a wide array of data types including strings, numbers, booleans, arrays, objects, and any amalgamation thereof.
Example ofuseState
:
import React, { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click to increase count</button>
</div>
);
}
The provided code snippet creates a counter that increments upon button click.
2. useEffect
Hook
The problem: Imagine we're fetching data from an API and storing it in a state variable. Each time this variable changes, it triggers a re-render of the component. This, in turn, prompts another API call, creating an infinite loop of requests.
Solution:useEffect
Hook. ACode within the useEffect
hook executes only during the initial render and subsequently whenever there's a change in the specified dependency.
Syntax:useEffect(() => {}, [dependency]);
Example:
import React, { useState, useEffect } from 'react';
function MyComponent({ id }) {
const [data, setData] = useState(null);
useEffect(() => {
fetch('https://my-api.com/data/${id}*')
.then(response => response.json())
.then(data => setData(data));
}, [id]);
return React.createElement("div", null, "MyComponent renders here!");
}
In the above code we are sending an API request and 'id' is used as the dependency for the useEffect
hook.
Top useEffect
use cases:-
Fetching API Data: Avoid making multiple requests to the server, particularly when dealing with user inputs like typing in a search field.
Input Field Validation: Validate input fields efficiently, minimizing unnecessary validations triggered by every character change.
3. useMemo
Hook
The useMemo hook is used for memorization, Effectively storing solutions to computations. Simply put, it caches the result of a function and recalculates it only when its dependencies change. It is similar to useEffect
hook, but it prevents from executing the code during the initial render. useMemo
also reduces a state variable, if we try to achieve the same thing with useEffect
.
As it doesn't result in any drastic improvement, it is rarely used.
Syntax: const memodVal = useMemo(() => {}, []);
Example:
import { useState, useMemo } from "react";
import ReactDOM from "react-dom/client";
const App = () => {
const [count, setCount] = useState(0);
const [todos, setTodos] = useState([]);
const calculation = useMemo(() => expensiveCalculation(count), [count]);
const increment = () => {
setCount((c) => c + 1);
};
const addTodo = () => {
setTodos((t) => [...t, "New Todo"]);
};
return (
<div>
<div>
<h2>My Todos</h2>
{todos.map((todo, index) => {
return <p key={index}>{todo}</p>;
})}
<button onClick={addTodo}>Add Todo</button>
</div>
<hr />
<div>
Count: {count}
<button onClick={increment}>+</button>
<h2>Expensive Calculation</h2>
{calculation}
</div>
</div>
);
};
const expensiveCalculation = (num) => {
console.log("Calculating...");
for (let i = 0; i < 1000000000; i++) {
num += 1;
}
return num;
};
In the above example, the expensive Calculation will not run on adding a todo, as it is wrapped inside useMemo
hook.
4. useRef
Hook
useRef
hook is very different from other hooks. It mainly has 2 use cases:-
It can be used to access a DOM element directly.
Let us understand this with an example
function App() { const inputElement = useRef(); const focusInput = () => { inputElement.current.focus(); }; return ( <> <input type="text" ref={inputElement} /> <button onClick={focusInput}>Focus Input</button> </> ); }
In the above example,
useRef
is used to access the DOM element input by giving it a reference. We can do multiple operations with this element. For eg. here we are focusing the element on clicking a button.
It can be used to store a mutable value that does not cause a re-render when updated.
This can be helpful in various ways. We can count the number of times the component is rendered in our application.
function App() {
const renderCounter = useRef(0);
renderCounter.current = renderCounter.current + 1;
return (
<>
</>
);
}
5. Custom Hooks
Hooks in React serve as reusable functions, empowering developers to create custom hooks tailored to their specific needs. By convention, all custom hooks must start with the keyword 'use'. For example, let us create a custom hook named useFetch
, designed to streamline the fetching logic across multiple components.
const useFetch = (url) => {
const [data, setData] = useState(null);
useEffect(() => {
fetch(url)
.then((res) => res.json())
.then((data) => setData(data));
}, [url]);
return [data];
};
This is how you can easily create custom hooks.
In conclusion, these custom hooks, alongside built-in ones, elevate the power and versatility of functional components in React. They simplify development and enhance the flexibility of React applications.
That's a wrap. Please share your thoughts below, and stay tuned for more insightful content in the future. Until next time!