https://github.com/ch0ripain/react-custom-hooks
🧙♂️ Working with custom hooks 🧙♂️
https://github.com/ch0ripain/react-custom-hooks
frontend react react-custom-hooks reactjs web-development
Last synced: about 1 month ago
JSON representation
🧙♂️ Working with custom hooks 🧙♂️
- Host: GitHub
- URL: https://github.com/ch0ripain/react-custom-hooks
- Owner: ch0ripain
- Created: 2024-12-19T22:09:07.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-12-20T02:45:59.000Z (over 1 year ago)
- Last Synced: 2025-04-08T19:53:09.466Z (about 1 year ago)
- Topics: frontend, react, react-custom-hooks, reactjs, web-development
- Language: JavaScript
- Homepage:
- Size: 4.21 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
🧙♂️ Custom Hooks 🧙♂️
A custom hook is simply a normal JS function whose purpose is to wrap all the state/logic which is closely-related and repetitive to use it wherever you want avoiding that boilerplate code and encouraging reusability.
In this project, i used a custom hook to group up a fetch feature that manages 3 related states and some logic
```javascript
//states
const [userPlaces, setUserPlaces] = useState([]);
const [isFetching, setIsFetching] = useState(false);
const [error, setError] = useState();
//logic
useEffect(() => {
async function fetchPlaces() {
setIsFetching(true);
try {
const places = await fetchUserPlaces();
setUserPlaces(places);
} catch (error) {
setError({ message: error.message || 'Failed to fetch user places.' });
}
setIsFetching(false);
}
fetchPlaces();
}, []);
```
## Creating the Custom Hook 🔧
I organized the project by adding a hooks folder and a useFetch.js file.
- folder ➡️ can also be named customhooks or anything descriptive.
- file ➡️ name must start with use to comply and take advantage of React Hooks Rules
```javascript
export function useFetch(fetchFn,initialValue){
//modified states
const [isFetching, setIsFetching] = useState(false);
const [data, setData] = useState(initialValue);
const [error, setError] = useState();
//modified logic
useEffect(() => {
async function fetchData() {
setIsFetching(true);
try {
const data = await fetchFn();
setData(places);
} catch (error) {
setError({ message: error.message || 'Failed to fetch data.' });
}
fetchData(false);
}
fetchPlaces();
}, [fetchFn]);
return {
isFetching,
data,
setData,
error
}
```
- Generalize state/logic ➡️ state and logic variables names are now more generic.
- Flexible Parameters ➡️ added fetchFn and initialValue to allow dynamic usage.
- Effect Dependencies ➡️ ensured fetchFn is listed as a dependency for proper reusability.
- Reusability ➡️ returns an object containing all values and functions to expose.
## Using the Custom Hook 🔄
Now, this custom hook can be used as follows:
```javascript
import { useFetch } from "./hooks/useFetch.js";
const { isFetching, data: userPlaces, error } = useFetch(fetchUserPlaces, []);
...
{error && }
```
## Another Use Case: Nested Logic in Fetch 🎩
In AvailablePlaces.jsx, I needed to fetch available places and sort them by user location using the navigator API:
```javascript
useEffect(() => {
...
navigator.geolocation.getCurrentPosition((position) => {
const sortedPlaces = sortPlacesByDistance(
places,
position.coords.latitude,
position.coords.longitude
);
...
}
```
To integrate this with the custom hook, a customized fetch function was needed:
```javascript
//create a function with all the nested behavior what is needed
async function fetchSortedPlaces(){
const places = await fetchAvailablePlaces() // first retrieve all that places
//then returns a Promise with the resolve (sortedPlaces) or reject (not handled in this case)
return new Promise((resolve,reject) => {
navigator.geolocation.getCurrentPosition((position) => {
const sortedPlaces = sortPlacesByDistance(
places,
position.coords.latitude,
position.coords.longitude
);
resolve(sortedPlaces)
})
})
}
```
Now, use the custom hook with the fetch function
```javascript
const { isFetching, data: availablePlaces, error } = useFetch(fetchSortedPlaces, []);
```
## Quick Recap 🔄
- Create a reusable custom hook file (useFn.js) to manage some closely-related state/logic.
- Generalize the state/logic and also add parameters for flexibility.
- Handle other use cases with custom functions (async/Promise).
Finally, the project is cleaner and the custom hook can be easily reused across components as it is unique to each component's use.
---
🐸 This project is a practice exercise I learned from the Academind's React Course 🐸