For working professionals
For fresh graduates
More
5. React Table
8. Context API
In the world of web development, React is a highly efficient JavaScript library used to build user interfaces. React Hooks has revolutionized how developers handle state and lifecycle features in functional components. While built-in hooks like ‘useState’ and ‘useEffect’ offer substantial functionality, they sometimes fail to handle complex scenarios. This is where custom hooks come into play. They allow developers to write reusable, maintainable, and modular code.
Custom hooks in React provide a powerful mechanism to abstract component logic into reusable functions. This guide delves into custom hooks and demonstrates how they can be crafted to enhance code readability and reduce redundancy. From basic to advanced uses, we will explore how custom hooks can be tailored to specific needs, to streamline React projects.
Whether you are a novice or an experienced developer, let’s understand the basics of how to create custom hooks, go through practical examples, and discover best practices to test and deploy them in real-world applications.
A. Explanation of a Custom Hook in React JS In React, a custom hook is a JavaScript function that starts with 'use' and may call other hooks. It's a pattern that allows you to reuse stateful logic across multiple components without changing their structure. This means you can package part of a component's behavior into reusable chunks and share that logic across the application. Consider a custom hook called 'useFormInput' that manages form input states and handlers. Here's how to implement it:
import { useState } from 'react';
function useFormInput(initialValue) {
const [value, setValue] = useState(initialValue);
function handleChange(e) {
setValue(e.target.value);
}
return {
value,
onChange: handleChange,
};
}
export default useFormInput;
This hook can be used in any component to handle form inputs.
import React from 'react';
import useFormInput from './useFormInput';
function Form() {
const email = useFormInput('');
const password = useFormInput('');
function handleSubmit(event) {
event.preventDefault();
alert(`Email: ${email.value}, Password: ${password.value}`);
}
return (
<form onSubmit={handleSubmit}>
<label>
Email:
<input type="text" {...email} />
</label>
<label>
Password:
<input type="password" {...password} />
</label>
<button type="submit">Submit</button>
</form>
);
}
export default Form;
B. Comparison with Built-in HooksBuilt-in hooks like 'useState', 'useEffect', and 'useContext' provide foundational functionality in React. 'useState' is used to add state to functional components, and 'useEffect' is for side effects. Custom hooks build on these primitives and offer a way to encapsulate logic that utilizes basic hooks into reusable functions. This allows you to abstract component logic into cleaner, manageable code.
C. When and Why to Consider Creating Custom Hooks
When to create custom hooks:
Why create custom hooks:
If you are implementing a feature that requires fetching data from an API, instead of repeating the fetch logic in every component, you can create a 'useFetch' hook that can be reused wherever needed.
import { useState, useEffect } from 'react';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(url);
const result = await response.json();
setData(result);
setLoading(false);
} catch (error) {
setError(error);
setLoading(false);
}
};
fetchData();
}, [url]);
return { data, loading, error };
}
This hook can be used in any component to fetch data. It simplifies components and maintains consistency across projects.
Creating custom hooks in React can simplify component logic, particularly for tasks like handling form inputs. Here is the detailed process of setting up a simple custom hook called 'useFormInput', to manage the state and changes of form inputs.
npx create-react-app my-custom-hook-app
cd my-custom-hook-app
import { useState } from 'react';
function useFormInput(initialValue) {
const [value, setValue] = useState(initialValue);
function handleChange(e) {
setValue(e.target.value);
}
return {
value,
onChange: handleChange,
};
}
export default useFormInput;
File: 'useFormInput.js'
import { useState } from 'react';
function useFormInput(initialValue) {
const [value, setValue] = useState(initialValue);
function handleChange(e) {
setValue(e.target.value);
}
return {
value,
onChange: handleChange,
};
}
export default useFormInput;
Explanation:
Using the 'useFormInput' Hook in a ComponentLet’s use this custom hook in a functional component to handle form inputs.
File: 'App.js'
import React from 'react';
import useFormInput from './useFormInput';
function App() {
const name = useFormInput(''); // Initialize with empty string
const age = useFormInput(''); // Initialize with empty string
function handleSubmit(event) {
event.preventDefault();
alert(`Name: ${name.value}, Age: ${age.value}`);
}
return (
<form onSubmit={handleSubmit}>
<div>
<label>Name:</label>
<input type="text" {...name} />
</div>
<div>
<label>Age:</label>
<input type="text" {...age} />
</div>
<button type="submit">Submit</button>
</form>
);
}
export default App;
This approach ensures that each input's state management is encapsulated within the ‘useFormInput’ hook, reducing boilerplate and increasing reusability across your React application.
Advanced custom hooks in React allow the encapsulation and reuse of complex functionalities across projects. They integrate multiple built-in hooks, manage significant logic, and optimize performance.
Let's explore how to create a complex custom hook that involves multiple hooks and performance considerations.
Combining Multiple Built-in Hooks to Create a Complex Custom Hook
A powerful aspect of custom hooks is their ability to combine several built-in hooks to handle complex functionalities. This makes the code reusable and keeps component logic clean and maintainable.
Example: 'useUserProfile'
This custom hook might combine 'useState', 'useEffect', and 'useContext' to fetch, display, and manage a user profile.
import { useState, useEffect, useContext } from 'react';
import { UserContext } from './UserContext';
import { fetchUserProfile } from './api';
function useUserProfile(userId) {
const [profile, setProfile] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const { token } = useContext(UserContext);
useEffect(() => {
setIsLoading(true);
fetchUserProfile(userId, token)
.then(profile => {
setProfile(profile);
setIsLoading(false);
})
.catch(err => {
setError(err);
setIsLoading(false);
});
}, [userId, token]);
return { profile, isLoading, error };
}
Performance Considerations and Optimizations
When developing custom hooks, consider their performance impact, especially regarding unnecessary re-renders and memory leaks.
Example: 'useAuth' for Handling Authentication
Handling authentication is a common requirement for many applications. A 'useAuth' hook can manage authentication state, and user data, and provide methods for signing in and signing out.
import { useState, useEffect, useContext } from 'react';
import { authAPI, verifyToken } from './authenticationService';
function useAuth() {
const [user, setUser] = useState(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
const token = localStorage.getItem('token');
if (token) {
verifyToken(token)
.then(user => setUser(user))
.catch(err => {
console.error(err);
setError("Authentication failed");
localStorage.removeItem('token');
});
}
}, []);
const login = async (username, password) => {
setIsLoading(true);
try {
const user = await authAPI.login(username, password);
localStorage.setItem('token', user.token);
setUser(user);
setIsLoading(false);
} catch (error) {
setError(error);
setIsLoading(false);
}
};
const logout = () => {
localStorage.removeItem('token');
setUser(null);
};
return { user, login, logout, error, isLoading };
}
This 'useAuth' hook provides a modular and reusable way to integrate authentication throughout React applications. This ensures components that depend on user authentication can easily manage and respond to changes in authentication status.
Custom hooks in React provide an easy and simplified reuse functionality across projects. They help manage simple form inputs and handle complex authentication processes. Custom hooks enhance modularity and maintainability. By leveraging hooks, you can keep your components clean and focused, optimize performance, and accelerate your development process. As you advance, experimenting with and adopting custom hooks will elevate your React applications, making them efficient and easier to manage.
1. What are custom hooks in React?
Custom hooks in React are functions that let you hook into React state and lifecycle features from function components. They allow creation of reusable stateful logic that can be shared across multiple components.
2. What is a custom hook name in React?
In React, a custom hook name typically starts with 'use', followed by a description of its functionality, such as 'useFormInput' or 'useFetch'. This naming convention helps indicate that the function is a hook and adheres to React's rules of hooks.
3. What is the difference between custom hooks and HOCs?
Custom hooks and Higher-Order Components (HOCs) allow for the reusability of logic in React, differently. Custom hooks enable you to use React state and lifecycle features within function components through a hook function. They provide a more modular and flexible way to share logic by encapsulating it in functions that can be called within other functional components.
HOCs involve taking a component and returning a new component with extended or altered behavior. They wrap a component to inject additional props or alter its behavior, which can sometimes lead to more complex component hierarchies and less transparent code flow.
4. What are the 4 hooks in React?
The 4 fundamental hooks in React are:
i) 'useState': Manages state in functional components.
ii) 'useEffect': Handles side effects in functional components.
iii) 'useContext': This enables you to consume context values efficiently.
iv) 'useReducer': Offers more complex state logic than 'useState', similar to Redux.
5. Where do custom hooks React?
Custom hooks in React are used within functional components to encapsulate and reuse logic related to state, side effects, or other React features, making the code more modular and manageable.
Author
Start Learning For Free
Explore Our Free Software Tutorials and Elevate your Career.
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918045604032
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.