Skip to content

Commit

Permalink
Merge branch 'main' into add-tests-stale-dependents
Browse files Browse the repository at this point in the history
  • Loading branch information
dai-shi authored May 21, 2024
2 parents 1d089a5 + a685dfc commit 7194200
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 3 deletions.
4 changes: 4 additions & 0 deletions docs/guides/nextjs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,15 @@ Jotai provides SWC plugins for better DX while developing with Next.js. [Find mo

#### HN Posts

Page Router demo:

<Stackblitz
id="stackblitz-starters-cnz9lg"
file="store%2Findex.ts,pages%2F_app.tsx,pages%2Findex.tsx"
/>

App Router [demo on Stackblitz](https://stackblitz.com/edit/jotai-nextjs-app-router-demo?file=store%2Findex.ts,app%2Flayout.tsx,components%2FPost.tsx,app%2Fpage.tsx)

#### Next.js repo

```bash
Expand Down
3 changes: 0 additions & 3 deletions src/vanilla/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,6 @@ type PrdStore = {
}
type Store = PrdStore & Partial<DevStoreRev2>

export type INTERNAL_DevStoreRev2 = DevStoreRev2
export type INTERNAL_PrdStore = PrdStore

/**
* Create a new store. Each store is an independent, isolated universe of atom
* states.
Expand Down
18 changes: 18 additions & 0 deletions src/vanilla/store2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ type DevStoreRev4 = {
key: K,
fn: PrdStore[K],
) => void
dev4_restore_atoms: (values: Iterable<readonly [AnyAtom, AnyValue]>) => void
}

type PrdStore = {
Expand Down Expand Up @@ -681,6 +682,23 @@ export const createStore = (): Store => {
dev4_override_method: (key, fn) => {
;(store as any)[key] = fn
},
dev4_restore_atoms: (values) => {
const pending = createPending()
for (const [atom, value] of values) {
if (hasInitialValue(atom)) {
const aState = getAtomState(atom)
const hasPrevValue = 'v' in aState
const prevValue = aState.v
setAtomStateValueOrPromise(atom, aState, value)
mountDependencies(pending, atom, aState)
if (!hasPrevValue || !Object.is(prevValue, aState.v)) {
addPendingAtom(pending, atom, aState)
recomputeDependents(pending, atom)
}
}
}
flushPending(pending)
},
}
return store
}
Expand Down
36 changes: 36 additions & 0 deletions tests/vanilla/storedev.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,4 +136,40 @@ describe.skipIf(!IS_DEV_STORE2)('[DEV-ONLY] dev-only methods rev4', () => {
const weakMap = store.dev4_get_internal_weak_map()
expect(weakMap.get(countAtom)?.v).toEqual(1)
})

it('should restore atoms and its dependencies correctly', () => {
const store = createStore() as any
if (!('dev4_restore_atoms' in store)) {
throw new Error('dev methods are not available')
}
const countAtom = atom(0)
const derivedAtom = atom((get) => get(countAtom) * 2)
store.set(countAtom, 1)
store.dev4_restore_atoms([[countAtom, 2]])
expect(store.get(countAtom)).toBe(2)
expect(store.get?.(derivedAtom)).toBe(4)
})

it('should restore atoms and call store listeners correctly', () => {
const store = createStore() as any
if (!('dev4_restore_atoms' in store)) {
throw new Error('dev methods are not available')
}
const countAtom = atom(0)
const derivedAtom = atom((get) => get(countAtom) * 2)
const countCb = vi.fn()
const derivedCb = vi.fn()
store.set(countAtom, 2)
const unsubCount = store.sub(countAtom, countCb)
const unsubDerived = store.sub(derivedAtom, derivedCb)
store.dev4_restore_atoms([
[countAtom, 1],
[derivedAtom, 2],
])

expect(countCb).toHaveBeenCalled()
expect(derivedCb).toHaveBeenCalled()
unsubCount()
unsubDerived()
})
})

0 comments on commit 7194200

Please sign in to comment.