Skip to content

Commit

Permalink
add rehydrate and store options
Browse files Browse the repository at this point in the history
  • Loading branch information
akkadaska committed Nov 24, 2024
1 parent 3c06698 commit b027e5d
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 13 deletions.
14 changes: 11 additions & 3 deletions src/hydrate-atoms/HydrationBoundary.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
'use client';

import type { PropsWithChildren } from 'react';
import type { AnyWritableAtom, InferAtomTuples } from './types.js';
import type {
AnyWritableAtom,
HydrateAtomOptions,
InferAtomTuples,
} from './types.js';
import { useHydrateAtoms } from './use-hydrate-atoms.js';

export function HydrationBoundary<
T extends (readonly [AnyWritableAtom, ...unknown[]])[],
>({
children,
hydrateAtoms,
}: PropsWithChildren<{ hydrateAtoms: InferAtomTuples<T> }>) {
useHydrateAtoms(hydrateAtoms);
options,
}: PropsWithChildren<{
hydrateAtoms: InferAtomTuples<T>;
options?: HydrateAtomOptions | undefined;
}>) {
useHydrateAtoms(hydrateAtoms, options);

return <>{children}</>;
}
6 changes: 6 additions & 0 deletions src/hydrate-atoms/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { WritableAtom } from 'jotai';
import type { Store } from '../shared.js';

export type AnyWritableAtom = WritableAtom<unknown, never[], unknown>;

Expand All @@ -9,3 +10,8 @@ export type InferAtomTuples<T> = {
: T[K]
: never;
};

export type HydrateAtomOptions = {
store: Store;
rehydrateKey?: string | undefined;
};
20 changes: 13 additions & 7 deletions src/hydrate-atoms/use-hydrate-atoms.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { atom, useStore } from 'jotai';
import type { AnyWritableAtom, InferAtomTuples } from './types.js';
import type {
AnyWritableAtom,
HydrateAtomOptions,
InferAtomTuples,
} from './types.js';
import { useCallback, useEffect, useRef } from 'react';

export function useHydrateAtoms<
T extends (readonly [AnyWritableAtom, ...unknown[]])[],
>(hydrateAtoms: InferAtomTuples<T>) {
>(hydrateAtoms: InferAtomTuples<T>, options?: HydrateAtomOptions) {
const isHydratedRef = useRef(false);
const lastHydrateAtoms = useRef(hydrateAtoms);
const store = useStore();
const lastRehydrateKey = useRef(options?.rehydrateKey);
const store = useStore(
options?.store != null ? { store: options?.store } : undefined,
);

const hydrate = useCallback(() => {
store.set(isHydratingPrimitiveAtom, true);
Expand All @@ -23,11 +29,11 @@ export function useHydrateAtoms<
}

useEffect(() => {
if (lastHydrateAtoms.current !== hydrateAtoms) {
lastHydrateAtoms.current = hydrateAtoms;
if (lastRehydrateKey.current !== options?.rehydrateKey) {
lastRehydrateKey.current = options?.rehydrateKey;
hydrate();
}
}, [hydrate, hydrateAtoms]);
}, [hydrate, options?.rehydrateKey]);
}

const isHydratingPrimitiveAtom = atom(false);
Expand Down
3 changes: 3 additions & 0 deletions src/shared.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { createStore } from 'jotai';

export type Store = ReturnType<typeof createStore>;
5 changes: 2 additions & 3 deletions src/ssr-provider/SSRProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
'use client';

import { Provider, type createStore } from 'jotai';
import { Provider } from 'jotai';
import type { PropsWithChildren } from 'react';
import { useCreateStore } from './use-create-store.js';

type Store = ReturnType<typeof createStore>;
import type { Store } from '../shared.js';

function SSRProviderWithGivenStore({
store,
Expand Down

0 comments on commit b027e5d

Please sign in to comment.