diff --git a/packages/atoms/src/classes/Ecosystem.ts b/packages/atoms/src/classes/Ecosystem.ts index 09cc4f80..cc532271 100644 --- a/packages/atoms/src/classes/Ecosystem.ts +++ b/packages/atoms/src/classes/Ecosystem.ts @@ -287,6 +287,11 @@ export class Ecosystem | undefined = any> /** * Get an atom instance. Don't create the atom instance if it doesn't exist. * Don't register any graph dependencies. + * + * Tries to find an exact match, but falls back to doing a fuzzy search if no + * exact match is found. Pass atom params (or an empty array if no params or + * when passing a search string) for the second argument to disable fuzzy + * search. */ public find( template: A, @@ -302,7 +307,8 @@ export class Ecosystem | undefined = any> ): AtomInstanceType | undefined public find( - key: string + searchStr: string, + params?: [] ): AtomInstanceType | undefined public find( @@ -310,6 +316,7 @@ export class Ecosystem | undefined = any> params?: AtomParamsType ) { const isString = typeof template === 'string' + if (!isString) { const id = (template as A).getInstanceId(this, params) @@ -319,6 +326,18 @@ export class Ecosystem | undefined = any> if (instance) return instance } + // if params are passed, don't fuzzy search + if (params) { + return this._instances[ + isString + ? template + : `${template.key}-${this._idGenerator.hashParams( + params, + this.complexParams + )}` + ] + } + const matches = this.findAll(template) return ( @@ -328,10 +347,10 @@ export class Ecosystem | undefined = any> } /** - * Get an object of all atom instances in this ecosystem. + * Get an object of all atom instances in this ecosystem keyed by their id. * - * Pass an atom template or atom template key string to only return instances - * whose id weakly matches the passed key. + * Pass an atom template to only find instances of that atom. Pass an atom key + * string to only return instances whose id weakly matches the passed key. */ public findAll(template?: AnyAtomTemplate | string) { const isAtom = (template as AnyAtomTemplate)?.key diff --git a/packages/react/test/units/Ecosystem.test.tsx b/packages/react/test/units/Ecosystem.test.tsx index e31bea1d..97760da7 100644 --- a/packages/react/test/units/Ecosystem.test.tsx +++ b/packages/react/test/units/Ecosystem.test.tsx @@ -102,6 +102,25 @@ describe('Ecosystem', () => { ) }) + test('find() with params only returns exact matches', () => { + const atom1 = atom('1', (id?: string) => id) + const atom2 = atom('someLongKey1', 1) + const atom3 = atom('someLongKey11', 1) + const atom4 = atom('someLongKey111', 1) + + ecosystem.getInstance(atom1, ['a']) + ecosystem.getInstance(atom1) + ecosystem.getInstance(atom1, ['b']) + ecosystem.getInstance(atom2) + ecosystem.getInstance(atom3) + ecosystem.getInstance(atom4) + + expect(ecosystem.find('someLongKey', [])).toBeUndefined() + expect(ecosystem.find(atom1, ['b'])?.getState()).toBe('b') + expect(ecosystem.find(atom1, ['c'])).toBeUndefined() + expect(ecosystem.find(atom3, [])?.getState()).toBe(1) + }) + test('findAll() with no params returns all atom instances', () => { const atom1 = atom('1', (id: number) => id)