Introduction
In this blog, we will discuss React hooks, React Hooks are a powerful feature introduced in React that allows developers to use state and other React features without writing a class component. With hooks, you can add functionality to functional components, making them more versatile and reusable. We will discuss React hooks, including the various types of hooks available, their purposes, and when to use them. Additionally, we will explore practical examples to illustrate their usage. As In the previous blog we already discussed UseState Hook, In this, we will directly dive into the useEffect,useContext,useReducer and custom Hook.
useEffect:
The useEffect hook in React allows you to perform side effects in functional components. The first parameter to useEffect is a function that contains the side effect logic you want to execute, The second parameter to useEffect is an optional dependency array. It specifies the values that the effect depends on If the dependency array is empty, the effect will only run once. Let's consider an example
import React, { useState, useEffect } from 'react';
const PostList = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
const fetchPosts = async () => {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
setPosts(data);
} catch (error) {
console.error('Error occured:', error);
}
};
fetchPosts();
}, []);
return (
<div>
<h2>Post List</h2>
<ul>
{posts.map(post=> (
<li key={user.id}>{post.name}</li>
))}
</ul>
</div>
);
};
export default PostList;
In this example, the fetchPosts component fetches a list of posts from an API using the fetch function inside the useEffect hook. When the component mounts, the effect triggers the fetchPosts function, which performs an API call to retrieve the post data. The response is then converted to JSON format using response.json() and the resulting data is stored in the posts state using setPosts. Since the effect has an empty dependency array, it will run only once when the component mounts. The component renders the retrieved user data by mapping over the posts array and rendering a list item for each post.
useContext:
The useContext hook in React allows you to access the value of a context provided by a parent component. It simplifies the process of sharing data or functionality across multiple components without the need for prop passing through each component.
App component:
import React,{useState} from 'react'
import ComponentA from './ComponentA'
export const UserContex = React.createContext()
export const ContentContex = React.createContext()
const App = () => {
return (
<div>
<UserContex.Provider value={'John Cena'}>
<ContentContex.Provider value={'this is the description'}>
<ComponentA/>
</ContentContex.Provider>
</UserContex.Provider>
</div>
);
};
export default App;
ComponentA
import React from 'react'
import ComponentB from './ComponentB'
function ComponentA() {
return (
<div>
<ComponentB/>
</div>
)
}
export default ComponentA
ComponentB
import React,{useContext} from 'react'
import {UserContex,ContentContex} from '../App'
function ComponentB() {
const username = useContext(UserContex)
const content = useContext(ContentContex)
return (
<>
<h1>UseContext</h1>
<p>hellow {username}</p>
<p>{content}</p>
</>
)
}
export default ComponentB
In this example, we directly pass the value of username and content to ComponentB without passing through the ComponentA. The UserContex and ContentContex are created using createContext() from the React package. These contexts are exported for use in other components. Inside the App component, the UserContex.Provider is used to providing a value of ' John Cena 'to the UserContex.The ComponentA component is rendered inside the nested context providers. The ComponentA component renders the ComponentB component. In the ComponentB component, the username variable is assigned the value from the UserContex using the UseContext hook.
useReducer:
In React, the useReducer hook is a powerful tool that allows you to manage complex state and state transitions using a reducer function. By using useReducer, you can define a reducer function that takes the current state and an action as parameters, and returns the new state based on the action type. This pattern of state updates is known as a "reducer." The useReducer hook accepts two arguments: the reducer function and the initial state. It returns an array with two elements: the current state and a dispatch function. The dispatch function is used to trigger state updates by dispatching actions.
import React, { useReducer } from 'react';
const initialState = 0;
// Reducer function
const reducer = (state, action) => {
switch (action.type) {
case 'increment':
return state + 1;
case 'decrement':
return state - 1;
case 'reset':
return initialState;
default:
return state;
}
};
const Counter = () => {
const [count, dispatch] = useReducer(reducer, initialState);
return (
<div>
<h2>Counter: {count}</h2>
<button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
<button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
<button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
</div>
);
};
export default Counter;
In this example, we initialize the state initialState to 0. Then we define a reducer function that takes the current state and an action as parameters and returns the new state based on the action type. The reducer function uses a switch statement to handle different action types Increment, Decrement and Reset and updates the state accordingly. Inside the Counter component, we use the useReducer hook to create the count state and the dispatch function. The dispatch function is responsible for triggering state updates by dispatching actions.
custom Hook:
In React, custom hooks are a powerful feature that allows you to extract and reuse logic from functional components. Custom hooks enable you to create self-contained functions that can be shared across multiple components, promoting code reusability and encapsulation of logic. Create a new function starting with the prefix "use" such as, useNameofFunction().
useCounter.js
import {useState} from 'react'
function useCounter(initialState=0,value) {
const [count,setCount] = useState(initialState)
const increase = () => {
setCount(count+value)
}
const decrease = () => {
setCount(count-value)
}
const reset = () => {
setCount(initialState)
}
return [increase,decrease,reset,count]
}
export default useCounter
Counter.js
import React from 'react'
import useCounter from './useCounter'
function Counter() {
const [increase,decrease,reset,count] = useCounter(0,1)
return (
<div>
<h1>UseCustom HOOK</h1>
<h4>Counter:{count}</h4>
<button onClick={increase}>Incrementer</button>
<button onClick={decrease}>decrementer</button>
<button onClick={reset}>reset</button>
</div>
)
}
export default Counter
In this example, we have created a custom hook called useCounter that manages a counter state. The custom hook takes two parameters: initialState, which represents the initial value of the counter defaulted to 0, and value, which represents the increment or decrement value defaulted to 1. Inside the useCounter hook, we use the useState hook to create the count state and the setCount function to update it. The increase function increments the count by the provided value, the decrease function decrements the count by the value, and the reset function resets the count to the initialState. The hook returns an array containing the increase, decrease, reset, and count values. This allows components that use the useCounter hook to easily access and utilize these values.
Conclusion
In this blog, we have covered useEffcet, useReducer, useContext, and custom hooks. However, there are several other important concepts in React Hooks that you can explore as you progress such as useMemo, useRef, and useCallback. This provide further optimizations and capabilities. useMemo allows memoizing expensive calculations, useRef provides a way to access and store values across renders, and useCallback memoizes callback functions to avoid unnecessary re-renders.