Hello Friends,
In this post we are going to take a look on what is custom react hooks? why we need one? and how to create one when needed? Let us start with understand what is react hook first.
What is React Hook?
The React hooks are simple functions which can help you manange state data without using class component. With Hooks, you can use functional components to manage state and other features by using built-in functions such as useState, useEffect, useContext, and more.
In simple words, Hooks enables developer to write clearn code by providing simpler and concise way for managing state and other features in React applications.
There are multiple react hooks available, why we need to create one?
As you learned about react hooks, these are the functions created to handle generic requirement. for example, useState hook helps you manange state for a functional component. similarly, useEffect hook is used to call side-effects. but, if you have some specific need and you want to export that part of code as a new reusable functions so that other component can also use it, the custom react hooks are way to go. You might also be thinking why not just create a simple function and call it the places you need.
Why to create custom hooks when I can create a function and call it other places?
The main difference between custom hooks and other function is , custom hooks can manage stateful data and encapsulate other react hooks. You can not do this using simple javascript functions.
Here are some key differences between Custom React Hooks and Functions:
- State management: Custom React Hooks allow you to manage state using the useState Hook and other built-in Hooks, while functions do not have built-in state management.
- Reusability: Both Custom React Hooks and functions are reusable, but Custom React Hooks are specifically designed for encapsulating stateful logic and reusing it across multiple components.
- Use cases: Functions are more general purpose and can be used for a wide range of tasks such as calculations, validation, or data formatting. Custom React Hooks are more focused on stateful logic and side effects within a React component.
- Naming conventions: Custom React Hooks are named with the “use” prefix, which is a convention that signals to React that the function is a Hook and should be treated as such. Regular functions can be named anything you choose.
Let us start creating a new react application and try to see how to build custom react hooks.
First Let usĀ create new react application and use typescript with it using below command.
npx create-react-app my-app-customhooks-tutorial --template typescript
Open the application in vscode and create folders as per below snap.
Now, If you developed multiple react applications, you might be realized that most of the time, we need to get data from an API and then we keep that that using useState, we also keep another state to manage if we are in a process of fetchinng data or not and probably another one to show if there is some error while fetching data. We are going to build this use-case using React Custom Hooks.
Lets us now install axios using below command which we use mosily for calling API
npm i axios
How I am going to create fake APIs using mocki.io. I am going to pass below json and generate a fake api which will return the same json information when called.
{
"products": [
{
"id": 1,
"name": "Product 1",
"price": 9.99
},
{
"id": 2,
"name": "Product 2",
"price": 19.99
},
{
"id": 3,
"name": "Product 3",
"price": 29.99
},
{
"id": 4,
"name": "Product 4",
"price": 39.99
},
{
"id": 5,
"name": "Product 5",
"price": 49.99
}
]
}
This is the response from the site. https://mocki.io/v1/bf70f69a-ed5b-495a-aa66-2ebb021dd3ce
Create a new file named “useAPIData.tsx” in hooks folder and add below code in it.
import axios, { AxiosError } from "axios";
import { useEffect, useState } from "react";
function useAPIData(url: string) {
const [loading, setLoading] = useState(false);
const [data, setData] = useState<any>(null);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
try {
setLoading(true);
const response = await axios.get(url);
setData(response.data);
setLoading(false);
} catch (error: AxiosError | any) {
setError(error.message);
setLoading(false);
}
}
fetchData();
}, [url]);
return { loading, data, error };
}
export default useAPIData;
This is a custom React hook named useAPIData
that fetches data from a specified URL using Axios library and manages the state of loading, data, and errors associated with the API call using useState
hook.
When the hook is called with a url
parameter, it initializes three state variables with default values:
loading
variable withfalse
value indicating that data is not being fetched initially.data
variable withnull
value indicating that no data has been fetched yet.error
variable withnull
value indicating that no errors have occurred yet.
The hook returns an object with three properties: loading
, data
, and error
.
- The
loading
property indicates whether the API call is in progress or not. - The
data
property contains the response data from the API call if it was successful, otherwise, it remainsnull
. - The
error
property contains the error message if the API call was unsuccessful, otherwise, it remainsnull
.
The hook uses the useEffect
hook to execute the fetchData
function, which makes an API call using Axios library with the provided URL. If the API call is successful, the response data is set to the data
state variable, and loading
is set to false
. If the API call fails, the error message is set to the error
state variable, and loading
is set to false
.
The catch
block in fetchData
handles errors that occur during the Axios request. If the error is an Axios error, the error message is taken from the error.message
property. Otherwise, the entire error object is returned as the error message.
Finally, the hook is exported to be used in other components.
Note: when creating custom react hook you should be named with “use” prefix.
Create a new file named “product-list.tsx” in components folder and add below code in it.
import useAPIData from "../hooks/useAPIData";
function ProductList() {
const { loading, data, error } = useAPIData(
"https://mocki.io/v1/bf70f69a-ed5b-495a-aa66-2ebb021dd3ce"
);
if (loading) {
return <div>Loading...</div>;
}
if (data && data.products.length > 0) {
return (
<div>
{data.products.map((product: any) => (
<div key={product.id}>
<h3>{product.name}</h3>
<p>{product.price}</p>
</div>
))}
</div>
);
}
if (error) {
return <div>Error: {error}</div>;
}
return <div>No data</div>;
}
export default ProductList;
This is a React component named ProductList
that uses the useAPIData
custom hook to fetch product data from a specified URL and render it in the component.
The component first calls the useAPIData
hook with a mock URL that returns a JSON response containing an array of product data. The hook returns an object containing the loading
, data
, and error
states that are then destructured for use in the component.
The component uses conditional rendering to handle different states of the loading
, data
, and error
states.
If the loading
state is true, the component returns a loading message “Loading…”.
If the data
state exists and the length of the products
array is greater than 0, the component maps over the array and returns a product card for each product, which includes the product’s name and price.
If the error
state exists, the component returns an error message with the error message received from the useAPIData
hook.
If none of the above conditions are met, the component returns a message “No data”.
Finally, the ProductList
component is exported for use in other components.
Update “App.tsx” as below.
import React from "react";
import "./App.css";
import ProductList from "./components/product-list";
function App() {
return (
<div className="App">
<ProductList />
</div>
);
}
export default App;
This is a simple React component named App
that renders the ProductList
component inside a div with the class name “App”. The ProductList
component is imported from the ./components/product-list
file.
This component doesn’t have any additional logic, and it serves as the entry point of the application. It simply renders the ProductList
component, which fetches and displays a list of products using the useAPIData
hook. The className
attribute is used to apply styling to the div element using CSS.
Finally, the App
component is exported to be used in other parts of the application.
Now lets run the application using npm start and see the browser output. If everything works correctly, you should have output as below.
so, we can see our custom react hook is working correcly.
Summary
The blog post discusses Custom React Hooks, which are functions designed to encapsulate stateful logic and reusable across multiple components. The post explains why custom hooks are needed and how they differ from regular functions. The blog also demonstrates how to create a custom React hook using TypeScript and Axios to fetch data from an API, manage loading and error states, and return an object containing these values. The post provides code examples and step-by-step instructions to create a new React application and use TypeScript with it. The blog also includes a mock API and shows how to use it to generate fake data.