Skip to content

Commit

Permalink
feat(atomFamily): supports instanceof
Browse files Browse the repository at this point in the history
  • Loading branch information
dmaskasky committed Jul 30, 2024
1 parent aeeb479 commit c1110ef
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
7 changes: 6 additions & 1 deletion src/vanilla/utils/atomFamily.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,16 @@ export function atomFamily<Param, AtomType extends Atom<unknown>>(
}
}

const newAtom = initializeAtom(param)
const newAtom = Object.setPrototypeOf(
initializeAtom(param),
createAtom.prototype,
)
atoms.set(param, [newAtom, Date.now()])
return newAtom
}

createAtom.prototype = {}

createAtom.remove = (param: Param) => {
if (areEqual === undefined) {
atoms.delete(param)
Expand Down
69 changes: 69 additions & 0 deletions tests/vanilla/utils/atomFamily.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { expect, it, vi } from 'vitest'
import { Atom, atom, createStore } from 'jotai/vanilla'

Check failure on line 2 in tests/vanilla/utils/atomFamily.test.ts

View workflow job for this annotation

GitHub Actions / lint

'Atom' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.

Check failure on line 2 in tests/vanilla/utils/atomFamily.test.ts

View workflow job for this annotation

GitHub Actions / test_matrix (5.4.5)

'Atom' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.

Check failure on line 2 in tests/vanilla/utils/atomFamily.test.ts

View workflow job for this annotation

GitHub Actions / test_matrix (5.3.3)

'Atom' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.

Check failure on line 2 in tests/vanilla/utils/atomFamily.test.ts

View workflow job for this annotation

GitHub Actions / test_matrix (5.2.2)

'Atom' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.

Check failure on line 2 in tests/vanilla/utils/atomFamily.test.ts

View workflow job for this annotation

GitHub Actions / test_matrix (5.1.6)

'Atom' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.

Check failure on line 2 in tests/vanilla/utils/atomFamily.test.ts

View workflow job for this annotation

GitHub Actions / test_matrix (5.0.4)

'Atom' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled.
import { atomFamily } from 'jotai/vanilla/utils'

it('should create atoms with different params', () => {
const store = createStore()
const aFamily = atomFamily((param: number) => atom(param))

expect(store.get(aFamily(1))).toEqual(1)
expect(store.get(aFamily(2))).toEqual(2)
})

it('should remove atoms', () => {
const store = createStore()
const initializeAtom = vi.fn((param: number) => atom(param))
const aFamily = atomFamily(initializeAtom)

expect(store.get(aFamily(1))).toEqual(1)
expect(store.get(aFamily(2))).toEqual(2)
aFamily.remove(2)
initializeAtom.mockClear()
expect(store.get(aFamily(1))).toEqual(1)
expect(initializeAtom).toHaveBeenCalledTimes(0)
expect(store.get(aFamily(2))).toEqual(2)
expect(initializeAtom).toHaveBeenCalledTimes(1)
})

it('should remove atoms with custom comparator', () => {
const store = createStore()
const initializeAtom = vi.fn((param: number) => atom(param))
const aFamily = atomFamily(initializeAtom, (a, b) => a === b)

expect(store.get(aFamily(1))).toEqual(1)
expect(store.get(aFamily(2))).toEqual(2)
expect(store.get(aFamily(3))).toEqual(3)
aFamily.remove(2)
initializeAtom.mockClear()
expect(store.get(aFamily(1))).toEqual(1)
expect(initializeAtom).toHaveBeenCalledTimes(0)
expect(store.get(aFamily(2))).toEqual(2)
expect(initializeAtom).toHaveBeenCalledTimes(1)
})

it('should remove atoms with custom shouldRemove', () => {
const store = createStore()
const initializeAtom = vi.fn((param: number) => atom(param))
const aFamily = atomFamily<number, Atom<number>>(initializeAtom)
expect(store.get(aFamily(1))).toEqual(1)
expect(store.get(aFamily(2))).toEqual(2)
expect(store.get(aFamily(3))).toEqual(3)
aFamily.setShouldRemove((_createdAt, param) => param % 2 === 0)
initializeAtom.mockClear()
expect(store.get(aFamily(1))).toEqual(1)
expect(initializeAtom).toHaveBeenCalledTimes(0)
expect(store.get(aFamily(2))).toEqual(2)
expect(initializeAtom).toHaveBeenCalledTimes(1)
expect(store.get(aFamily(3))).toEqual(3)
expect(initializeAtom).toHaveBeenCalledTimes(1)
})

it('should support instanceof', () => {
const aFamilyA = atomFamily((param: number) => atom(param))
const aFamilyB = atomFamily((param: number) => atom(param))
expect(aFamilyA(1) instanceof aFamilyA).toEqual(true)
expect(aFamilyA(2) instanceof aFamilyA).toEqual(true)
expect(aFamilyA(1) instanceof aFamilyB).toEqual(false)
expect(aFamilyA(1) instanceof atom).toEqual(false)
expect(atom(2) instanceof aFamilyA).toEqual(false)
})

0 comments on commit c1110ef

Please sign in to comment.