I'm using this useFetch
custom hook in multiple components.
import {useState,useEffect} from 'react'
import {getToken} from './../services/token'
const useFetch = (url) => {
const [data,setData] = useState(null);
const [error,setError] = useState(null);
const [loading,setPending] = useState(false);
useEffect(() => {
(async()=>{
const abortCont = new AbortController();
const token = await getToken();
try {
setPending(true);
const response = await fetch(url,{
signal : abortCont.signal,
headers : {
"Content-Type" : "application/json",
"Authorization" : "Bearer "+token
}
});
const result = await response.json();
setData(result);
setPending(false);
} catch (err) {
if(err.name === 'AbortError'){
abortCont.abort();
return;
}
setError(String(err));
setPending(false);
}
})()
}, [])
return {data,error,loading}
}
export default useFetch;
And I import it in a users components as below.
const {data,error,loading} = useFetch('http://localhost:4040/users');
Normally I pass the second parameter of UseEffect
like [users.length]
to make the users data reactive but as this is a custom hook and being used in many components,
How can I make the users data to be reactive when users data was changed or updated?
You can pass the dependency array as the optional parameter to your custom hook.
const useFetch = async (url, deps) => {
const [data,setData] = useState(null);
const [error,setError] = useState(null);
const [loading,setPending] = useState(false);
useEffect(() => {
(async()=>{
const abortCont = new AbortController();
const token = await getToken();
try {
setPending(true);
const response = await fetch(url,{
signal : abortCont.signal,
headers : {
"Content-Type" : "application/json",
"Authorization" : "Bearer "+token
}
});
const result = await response.json();
setData(result);
setPending(false);
} catch (err) {
if(err.name === 'AbortError'){
abortCont.abort();
return;
}
setError(String(err));
setPending(false);
}
})()
}, deps || [])
return {data,error,loading}
}
export default useFetch;
Then call it like
const {data,error,loading} = useFetch('http://localhost:4040/users', [users.length]);
EDIT
In your case you want to have some more control over the rendering. So i'll say you have to modify your hook to support setting data for your mounted component.
const useFetch = async (url, holded, setHolded) => {
const [data,setData] = useState(null);
const [error,setError] = useState(null);
const [loading,setPending] = useState(false);
useEffect(() => {
(async()=>{
const abortCont = new AbortController();
const token = await getToken();
try {
setPending(true);
const response = await fetch(url,{
signal : abortCont.signal,
headers : {
"Content-Type" : "application/json",
"Authorization" : "Bearer "+token
}
});
const result = await response.json();
setData(result);
if(setHolded) {
setHolded(result);
}
setPending(false);
} catch (err) {
if(err.name === 'AbortError'){
abortCont.abort();
return;
}
setError(String(err));
setPending(false);
}
})()
}, (holded && setHolded && [holded,setHolded,url]) || [url])
return {data,error,loading}
}
export default useFetch;
Then call it like
const {data,error,loading} = useFetch('http://localhost:4040/users', users, setUsers);