I'm trying to load initial data inside a component based on an external variable. So I have this:
const { dossierId } = useParams();
const { loadDossierData } = useDossierContext();
useEffect(() => {
loadDossierData(dossierId);
}, [dossierId]);
So my application is receiving in the url a parameter called dossierId
. This parameter is used to load some initial data that must be stored in an accessible for all context.
The context looks like this:
const [dossier, setDossier] = useState({});
const { get } = useRestServices();
const loadDossierData = async (dossierId) => {
const result = await get('myurl/%/dossier', [dossierId]); // This 'get' wrapper just substitutes every % in the url by the items in the following array in the function
setDossier(result);
console.log('loadDossierData');
console.log(result);
};
return (
<DossierContext.Provider
value={{
dossier,
loadDossierData,
}}
>
{children}
</DossierContext.Provider>
);
};
export const useDossierContext = () => useCustomContext(DossierContext);
export default DossierProvider;
So this looks like a normal code:
- The application loads with an initial dossierId
- A call to
loadDossierData
is done with that new dossierId - A
REST
call is made and data is loaded from backend - The context state updates and the updated
dossier
variable is visible for everyone who wants to use it
This is the ideal flow, and I can see it working correct because of the forced console.log
:
Nice, no?
But the real problem comes here. In the initial call to the function, where I try to detect any dossierId
change, the useEffect is warning me about a missing dependency:
But if I add it to the dependency array, my application runs in an infinite loop:
I'm trying to improve the way this information is get
and stored
in a shared context, but I keep fighting with this re-render thing and I didn't find a solution yet.
Any idea on how to avoid this? I know why the re-render is happening, but I need this flow and I'm not sure on how to do it and avoid re-renders.
Thanks a lot!
CodePudding user response:
You have to use useCallback
to prevent loadDossierData
from re-rendering.
const loadDossierData = useCallback(async (dossierId) => {
const result = await get('myurl/%/dossier', [dossierId]); // This 'get' wrapper just substitutes every % in the url by the items in the following array in the function
setDossier(result);
console.log('loadDossierData');
console.log(result);
}, [setDossier]);