I’m writing a web application using React.
In my code I have plenty different calls to the database.
All of this calls look very similar.
The only difference are table names and parameters and therefore I have a lot of functions that fetch the data.
For this reason I figured that I will write a generic hook that will take care of all my API calls.
The hook looks like this:
"use client"
import { useState, useEffect } from 'react';
export function useAWSGenericRequest(fetch_callback) {
const [value, setValue] = useState({
status: "pending",
value: []
});
useEffect(() => {
fetch_callback().then(function(request) {
request.on("success", function(response){
setValue(function() {
return {
status: "success",
value: response}
});
});
request.send();
});
}, []);
return { value: value, setValue: setValue };
}
Then in the code I use it like this:
import { FetchUsers } from '@/app/lib/fetch-users.js';
import { useAWSGenericRequest } from '@/app/ui/hooks/use-aws-generic-request.js'
.
.
.
export default function ListOfUsers(props) {
const users = useAWSGenericRequest(FetchUsers);
.
.
.
return (users.value.value.data.Users.map(function(user, i)
=> return (<div key={i}>{user.email}</div>)));
}
This code is simplified but it portrays the problem that I have.
The nested structure of my API response “users.value.value.data.Users” causes my user interface to be no longer responsive once the “users.value.value.data.Users” changes.
I read on the internet that react will not react on the nested array changes.
One solution would be to modify the generic hook that I mentioned earlier and make it look like this:
"use client"
import { useState, useEffect } from 'react';
export function useAWSGenericRequest(fetch_callback) {
const [value, setValue] = useState([]);
useEffect(() => {
fetch_callback().then(function(request) {
request.on("success", function(response){
setValue(function() {
return response.value.data.Users);
});
request.send();
});
}, []);
return [value, setValue];
}
Then in the code I could use it like this:
import { FetchUsers } from '@/app/lib/fetch-users.js';
import { useAWSGenericRequest } from '@/app/ui/hooks/use-aws-generic-request.js'
.
.
.
export default function ListOfUsers(props) {
const [users, setUsers] = useHandleGetSupplementById(supplement_id);
.
.
.
return (users.map(function(user, i)
=> return (<div key={i}>{user.email}</div>)));
}
In this case React does react and reloads the user interface every time I change the “users” array.
The problem obviously is that If I wanted to fetch some other value then I would need to copy my hook and replace the dotted path to get the resource I’m interested in like in this example response.value.some.other.value:
"use client"
import { useState, useEffect } from 'react';
export function useAWSGenericRequest(fetch_callback) {
const [value, setValue] = useState([]);
useEffect(() => {
fetch_callback().then(function(request) {
request.on("success", function(response){
setValue(function() {
return response.value.some.other.value);
});
request.send();
});
}, []);
return [value, setValue];
}
I feel like I’m missing some very simple trick/pattern but I just don’t know what it is.
Is there a way to create a generic hook like I’m trying to or do I need to accept the fact that I have create new hook for each new API call?
Best Regards