If I fetch dynamic data, how can I put it into an atomFamily without violating the rule of hooks? useSetRecoilState
requires me to pass in atomFamily(someIndex)
, but with dynamic data I don't have the someIndex
until after fetching the data. So it seems like I should have const setterFactory = someKey => useSetRecoilState(useAtomFamily(someKey))
but that violates the rule of hooks.
Example:
Assume I have an API response with accompanying type (and recoil atomFamily)
type Foo = unknown & { index: string }
type Response = {
foos: Foo[]
}
const myAtomFamily = useAtomFamily<Foo, string>({
key: 'foo',
default: null,
})
declare const fetchFromApi = () => Promise<Foo[]>
So if I have in a custom hook,
const myHook = () => {
const fooSetter = useSetRecoilState(myAtomFamily(???))
useEffect(() => {
fetchFromApi().then(foos => {
foos.forEach(foo => fooSetter(???)(???))
})
}, [])
}
You can you use the useRecoilCallback
hook for that, which is basically a factory hook that gives you access to the set
function:
const useMyHook = () => {
const fetchAndSet = useRecoilCallback(({set}) => async () => {
const foos = await fetchFromApi();
foos.forEach(foo => set(myAtomFamily(foo.id), foo))
}, [])
useEffect(fetchAndSet, [])
}