Closed natew closed 2 years ago
Actually, went further into it and I'd need atomFamily/selectorFamily to support this either way.
WhileuseAtoms
would be something that can only be implemented in core, I would like to understand its use case.
Would this be possible in order to reduce having a ton of hooks?
If you already know concrete atoms, you can just create a custom hook. So, I assume you would like to do like
const ... = useAtoms([atomA, atomB, ...]);
// or useAtoms(atomA, atomB, ...)
But then how would you use the result?
Thanks for raising this issue for discussion!
The basic use case is to wrap this in a proxy;
class Store {
x = 1
get y() { return this.x+ 1 }
}
function Component() {
const store = useStore(Store) // proxifies and turns all values into atoms, all get values into selectors
// tracks access only on access
store.y
useEffect(() => {
store.x = 10 // sets the atom
}, [])
}
Note, you’d need to access a dynamic amount of atoms per render, and it could change. This the need for a syntax where I don’t have more than one hook.
Second part is that I’d like to be able to have different namespaces for stores. A lot like a selectorFamily/atomFamily but at the store level:
class Store {
x = 1
get y() { return this.x+ 1 }
}
function Component() {
const store = useStore(Store, { id: 1 }) // gets a unique idempotent store
// ...
}
I'm not 100% convinced if your use case matches with the atom abstraction. I would probably create a single state for a store and use use-context-selector.
That said, I'm not against to create useAtoms
for possible use cases.
const [[atomAValue, atomASet], ...] = useAtoms([atomA, atomB, atomC]);
Does this look OK? Do you know if Recoil provides such primitive hook?
Ideally, better would be to not have it "subscribe" to an atom unless called for
Even with this API, you can do this: Just only pass atoms you want to subscribe.
(On second thought, I'm not sure how the implementation is easy.)
I don't think it's a good idea. If you did something like this (dynamically change the array)
const [...] = useAtoms(isUsingB ? [atomA, atomB] : [atomA]);
Then you'd be breaking the rules of hooks. Allowing an API like useAtoms
doesn't seem like a good idea to me.
And if you don't need to change the atoms array on the fly, then just do a custom hook:
const useMyAtoms = () => {
const a = useAtom(atomA);
const b = useAtom(atomB);
const c = useAtom(atomC);
return [a, b, c];
};
const Component = () => {
const [[], [], []] = useMyAtoms();
}
Oops, this is an old issue. Forgot to close it.
In Jotai API, we do this:
const Component = () => {
const [value1, value2, value3] = useAtomValue(useMemo(() => atom(
(get) => [get(atom1), get(atom2), get(atom3)]
), []));
// ...
};
Then you'd be breaking the rules of hooks.
We could avoid breaking the rules. But, it's not very intuitive, DX-wise. Anyway, we don't have such a hook in jotai. Neither in use-atom.
Would this be possible in order to reduce having a ton of hooks? Something like:
Edit: accidentally hit submit early...
Ideally, better would be to not have it "subscribe" to an atom unless called for (this is continuing off previous discussion), could be something like this: