From ef47a00fc8fd6fb2ad3e568ad13d3522607d8be8 Mon Sep 17 00:00:00 2001 From: Joshua Claunch Date: Sun, 16 Mar 2025 09:58:16 -0400 Subject: [PATCH] fix(react): use scope in `useAtomContext` when using default params --- packages/react/src/hooks/useAtomContext.ts | 12 ++++++-- .../test/integrations/react-context.test.tsx | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/packages/react/src/hooks/useAtomContext.ts b/packages/react/src/hooks/useAtomContext.ts index 1e43d60d..8ffa0324 100644 --- a/packages/react/src/hooks/useAtomContext.ts +++ b/packages/react/src/hooks/useAtomContext.ts @@ -9,7 +9,7 @@ import { } from '@zedux/atoms' import { useContext } from 'react' import { useEcosystem } from './useEcosystem' -import { getReactContext } from '../utils' +import { getReactContext, reactContextScope } from '../utils' /** * A React hook that accepts an atom template and returns an atom instance of @@ -78,5 +78,13 @@ export const useAtomContext: { return instance } - return ecosystem.getInstance(template, defaultParams) + ecosystem.S = reactContextScope + + try { + return ecosystem.getNode(template, defaultParams) + } finally { + // We shouldn't need to capture/restore previous `S`cope. There should be no + // way for React to be rendering inside another scope. + ecosystem.S = undefined + } } diff --git a/packages/react/test/integrations/react-context.test.tsx b/packages/react/test/integrations/react-context.test.tsx index 4bb7b775..01ace0c2 100644 --- a/packages/react/test/integrations/react-context.test.tsx +++ b/packages/react/test/integrations/react-context.test.tsx @@ -1,6 +1,7 @@ import { atom, AtomProvider, + injectEffect, useAtomContext, useAtomInstance, useAtomValue, @@ -221,4 +222,31 @@ describe('React context', () => { expect(() => renderInEcosystem()).toThrowError(pattern) }) + + test('useAtomContext with default params flags the context as unsafe before getting the instance', () => { + const calls: any[] = [] + + const atom1 = atom('1', (id: string) => { + injectEffect(() => { + calls.push(id) + }) + + return id + }) + + function Test() { + const instance = useAtomContext(atom1, ['a']) + + return instance.get() + } + + renderInEcosystem() + + expect(calls).toEqual([]) + expect(ecosystem.asyncScheduler.j.length).toEqual(1) + + ecosystem.asyncScheduler.flush() + + expect(calls).toEqual(['a']) + }) })