An open API service indexing awesome lists of open source software.

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: 3 months ago
JSON representation

🧙‍♂️ Working with custom hooks 🧙‍♂️

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 🐸