I'm starting to use hooks in React and I got stuck, when I realized I would need an array of hooks to solve my problem. But according to the Rules of Hooks
Only Call Hooks at the Top Level
I'm not allow to call hooks inside a loop (and I guess also not in map).
My custom hook subscribes to an API and adds data to the state when there is an update:
export const useTrace = (id) => {
[trace, setTrace] = useState([])
useEffect(() => {
Api.getCurrentTrace(id)
.then(currentTrace => {
setTrace(currentTrace)
})
}, [id])
useEffect(() => {
Api.subscribeTraceUpdate(onUpdateTrip)
return () => {
Api.unsubscribeTraceUpdate(onUpdateTrip)
}
}, [])
const onUpdateTrip = msg => {
if (msg.id === id) {
setTrace([msg.data].concat(trace))
}
}
}
In my component I have a state with an array of IDs. For each ID I would like to use the useTrace(id) hook somehow like this:
import DeckGL from '@deck.gl/react'
function TraceMap({ ids }) {
const data = ids.map((id) => ({
id,
path: useTrace(id)
}))
const pathLayer = new PathLayer({
id: 'path-layer',
data,
getPath: d => d.path
})
return <DeckGL
layers={[ pathLayer ]}
/>
}
For the sake of simplicity I got ids as a property instead of having a state.
Why not have a useTraces custom hook rather than useTrace. This new hook can take an array of ids instead of a single id.
export const useTraces = (ids) => {
[traces, setTraces] = useState([]);
useEffect(() => {
(async () => {
const traces = await Promise.all(
ids.map((id) => Api.getCurrentTrace(id))
);
setTraces(traces);
})();
}, [ids]);
// ...
};
Another idea might be to create a sub component and use your hook in each of them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With