Closed Yarden-Ankonina closed 3 months ago
I don't have any suggestions outside of the current tedious approach you mentioned above.
Brainstorming: AtomFamily is a just a function but we can assume it returns atoms since we want to pass it in to atoms prop. Perhaps jotai-scope could expose a utility to scope functions.
import { scopableFn, ScopeProvider } from 'jotai-scope'
const scopableAtomFamily = scopableFn(atomFamily((id) => atom(id)))
<ScopeProvider atoms={[scopableAtomFamily]}>{children}</ScopeProvider>
Impl might look something like this:
type AtomFn = <T = unknown>(...args:T[]) => Atom<T>
const SCOPABLE = Symbol()
function ScopeFnAtom(fn: AtomFn, sub: Store['sub']) {
return Object.assign(
Atom(null),
fn,
{ type: SCOPABLE, sub }
)
}
export function scopableFn<T extends AtomFn>(fn: T): T & Atom<ReturnType<T>> {
const store = createStore()
const i = function interceptor(...args: unknown[]) {
const r = fn(...args)
store.set(a, r)
return r;
}
cons sub = store.sub.bind(a)
const a = ScopeFnAtom(i, sub)
return a
}
export function ScopeProvider({ atoms }) {
const [rAtoms, setRAtoms] = useState(new Set())
const scopedAtoms = new Set([...atoms, ...rAtoms])
function initialize(scopedAtoms) {
return { scopedAtoms, store: createScopedStore() }
}
const [state, setState] = useState(initialize())
if (!isSameSet(state.scopedAtoms, scopedAtoms) {
setState(initialize(scopedAtoms))
}
// subscribe to new rAtoms
useEffect(() => {
const unsubs = Array.from(state.scopedAtoms)
.filter((a) => SCOPABLE in a)
.map((a) => {
a.sub((r) => {
setRAtoms((rSet) => {
new Set([...rSet, r])
})
})
})
return () => unsubs.forEach(unsub => unsub())
}, [state])
const memoizedChildren = useMemo(() => children, [state])
return <Provider store={state.store}>{children}</Provider>
}
I'm encountering challenges while managing dynamic
atomFamily
instances within theScopeProvider
.Currently, I'm unable to directly pass the entire
atomFamily
into the atom array ofScopeProvider
. Instead, I'm forced to extract each individual atom and pass them separately. This approach becomes cumbersome in my application, where I heavily rely onatomFamily
for its functionality. Manually tracking and passing every single atom instance is quite tedious and doesn't seem an option currently.Ideally, I'd like to pass an entire
atomFamily
group into theScopeProvider
.Is there a recommended approach to address this scenario? Any suggestions or workarounds would be greatly appreciated.