I have multiple tables, of small size, and I want to be able to write / read / update my components when the corresponding table has been updated by the app (we can consider it's a single user app for the moment).
I've been inspired by this question to write a custom Provider and associated hook for data fetching (and eventually posting) in my app: React useReducer async data fetch
I came up with this:
import React from "react";
import { useContext, useState, useEffect } from "react";
import axios from "axios";
const MetadataContext = React.createContext();
function MetadataContextProvider(props) {
let [metadata, setMetadata] = useState({});
async function loadMetadata(url) {
let response = await axios.get(url);
// here when I console.log the value of metadata I get {} all the time
setMetadata({ ...metadata, [url]: response.data });
}
async function postNewItem(url, payload) {
await axios.post(url, payload);
let response = await axios.get(url);
setMetadata({ ...metadata, [url]: response.data });
}
return (
<MetadataContext.Provider value={{ metadata, loadMetadata, postNewItem }}>
{props.children}
</MetadataContext.Provider>
);
}
function useMetadataTable(url) {
// this hook's goal is to allow loading data in the context provider
// when required by some component
const context = useContext(MetadataContext);
useEffect(() => {
context.loadMetadata(url);
}, []);
return [
context.metadata[url],
() => context.loadMetadata(url),
(payload) => context.postNewItem(url, payload),
];
}
function TestComponent({ url }) {
const [metadata, loadMetadata, postNewItem] = useMetadataTable(url);
// not using loadMetadata and postNewItem here
return (
<>
<p> {JSON.stringify(metadata)} </p>
</>
);
}
function App() {
return (
<MetadataContextProvider>
<TestComponent url="/api/capteur" />
<br />
<TestComponent url="/api/observation" />
</MetadataContextProvider>
);
}
export default App;
(the code should run in CRA context, both apis can be replaced with almost any API)
When I run it, a request is fired on both endpoints (/api/capteur and /api/observation), but where I'm expecting the metadata object in the MetadataContextProvider to have 2 keys: "/api/capteur" and "/api/observation", only the content of the last request made appears.
When I console.log metadata in the loadMetadata function, metadata always has the initial state hook value, that is {}.
I'm fairly new to React, I tried hard and I'm really not figuring out what's going on here. Can anyone help?