In this article we will answer every question in your thoughts so be ready and lets get started. Lets understand how custom hooks works and how actually hooks works in practice.
We see a lot of things can be done by custom hooks but we don’t know why, when & where to use it?
What is Custom Hook.
Custom hooks in React are reusable JavaScript functions that allow you to extract and share stateful logic between components.
There are alot of stuff that we have to do in our apps that react didn’t give us out of the box so they introduced the Custom Hooks concept to make our own.
Without wasting anytime let’s go deep into this.
tip: First of all not all hooks or custom-hooks return [value, setValue] type of thing this is just and array useState return with 0 and 1 index and in 0 index it return the value and in 1 index it returns the function to change 0 index value
const useStateOwn = (defaultValue:any) => {
let state = defaultValue
const setChangeState = (changeValue:any) => {
state = changeValue
}
return [state,setChangeState]
}
This is a simplified example of how useState works internally. It’s not React’s real implementation, just for your understanding.
Now let’s understand how to create custom hook & later we understand when and why we should use this hook.
This is the basic of the basic custom hook.
export function useCustomHook() {
return 'some text return'
}
This is the basic custom hook. It may looks like a function but it’s not.
Hooks are used inside Functional Components & Custom Hooks not anywhere else. Wait what did i just say, custom hooks are used inside custom hooks ?
Will explain you later. First let’s just find the difference between custom hooks and functions.
Let’s say you have 2 functions
function foo () {
return 10
}
function bar () {
// we can all another function here
const fooValue = foo(); // just like this one
return fooValue
}
We can call 1 function into another function as you see the above, but the problem relies with hooks / custom hooks is that we cannot call custom hooks inside of the functions.
Let me just create an example of that as well for better understanding.
function getDataCurrent (){
const currentData = useCustomHook() // just like this one
// because using this in function will give us this error
/*
React Hook "useCustomHook" is called in function "getDataCurrent"
that is neither a React function component
nor a custom React Hook function. React component names must
start with an uppercase letter.
React Hook names must start with the
word "use".eslintreact-hooks/rules-of-hooks
*/
}
// as you see the error clearly most of the things got clear
There is few rules that you have to remember and that’s it.
- it must start with “use” string
- it cannot be call inside an function or nested function
- any open return statement will be use after hooks.
Now that we know the basic of How Custom hook is created and when / where is should be created.
Let’s move on to the usecase of custom hooks.
function useTestCustomHook () {
// you can call whatever inside a custom hook.
// useCustomHook() ! a custom hook
// test() ! a function
// <Page/> ! a Component
}
In this example we created custom hook with a name “useTestCustomHook” but as you see in the comments i’ve clearly mention that custom hook will call anything inside of it. Just because it’s an client side code so you can use anything of clientside inside of it.
You can doo unlimited stuff with custom hooks let me explain.
- You can return function / functions
- You can return multiple useStates at once to make your code clean even throught it is used in only single file.
- You can split your logic and UI from to make the code even more organized.
- You can pass arguments into customHook and use them accordingly just like a function but with hooks power.
We will go into the logic section later where we can show the before & after effect of using custom hook so stay tuned.
Hope you understand this soo far and I’m trying my best to make this topic as simple as possible.
Let’s move to the practical example.
Let’s say we have 2 components that needs user data and that user data will fetch from api and save on state,
If we normally do that we have to call that api in both components and save there data on seperate states and when something changes we have to change those 2 components as well and vise versa.
Okey now suppose we have UserProfile & UserSettings components.
First I’ll create those 2 components without custom hook and see what it looks like.
Now we have UserProfile component that looks like this.
import { useEffect, useState } from 'react'
import axios from 'axios'
function UserProfile() {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
setIsLoading(true);
try {
const response = await axios.get(`/api/user`);
setData(response.data);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
}
fetchData();
}, []);
if (isLoading) return <p>Loading user data...</p>;
if (error) return <p style={{ color: 'red' }}>Error loading user: {error.message}</p>;
return (
<div>
<h3>{data.name}</h3>
<p>Email: {data.email}</p>
<p>Phone: {data.email}</p>
</div>
);
}
And we have UserSettings Component which looks like this.
import { useEffect, useState } from 'react'
import axios from 'axios'
function UserSettings() {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
setIsLoading(true);
try {
const response = await axios.get(`/api/user`);
setData(response.data);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
}
fetchData();
}, []);
if (isLoading) return <p>Loading user data...</p>;
if (error) return <p style={{ color: 'red' }}>Error loading user: {error.message}</p>;
return (
<div>
<h3>Settings Page</h3>
<p>Email: {data.email}</p>
</div>
);
}
As you see the codebase above 80% of the codebase is same only the return statement have some changes but if we don’t know custom hooks we usually do stuff like this and this is i call garbage code.
Now let’s create a custom and see how this makes our life easier.
const useUserData =()=>{
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
async function fetchData() {
setIsLoading(true);
setError(null);
try {
const response = await axios.get(`/api/user`);
setData(response.data);
} catch (err) {
setError(err);
} finally {
setIsLoading(false);
}
}
fetchData();
}, []);
return {
data,
isLoading,
error
}
}
Now that we have custom hook we can update the logic in both UserProfile and UserSettings and see how this optimized the workflow.
UserProfile.jsx
function UserProfile() {
const { data, isLoading, error} = useUserData()
if (isLoading) return <p>Loading user profile...</p>;
if (error) return <p style={{ color: 'red' }}>Error loading user: {error.message}</p>;
return (
<div>
<h3>{data.name}</h3>
<p>Email: {data.email}</p>
<p>Phone: {data.email}</p>
</div>
);
}
UserSettings.jsx
function UserSettings() {
const { data, isLoading, error} = useUserData()
if (isLoading) return <p>Loading user profile...</p>;
if (error) return <p style={{ color: 'red' }}>Error loading user: {error.message}</p>;
return (
<div>
<h3>Settings</h3>
<p>Email: {data.email}</p>
</div>
);
}
Now that if we need to change anything in API we just have to update the custom hooks and all the components which are dependent on that hook will automatically reflect that change, So you don’t need to update each and every component from now on.
tip: You can return jsx / tsx statement from hooks and it will be used in different component. Let’s say you have a {data.name} component and you think that component will later need some modifications so you can just return the component and then later use that in Components like that {badge} and send that using return statement .. return { badge:… }.. like this.
And there you have it.
Hope this article made your life a little easy/better.
If you want my assistence please reach me out on Github & Linkedin.





Top comments (0)