Skip to content

Commit

Permalink
Merge pull request #11 from jotaijs/feat/refactoring-core-functionality
Browse files Browse the repository at this point in the history
Refactoring Core Functionality
  • Loading branch information
akkadaska authored Jan 4, 2025
2 parents 52ebf11 + e32a21d commit 05be6e5
Show file tree
Hide file tree
Showing 9 changed files with 405 additions and 242 deletions.
476 changes: 316 additions & 160 deletions README.md

Large diffs are not rendered by default.

42 changes: 0 additions & 42 deletions src/HydrationBoundary.tsx

This file was deleted.

27 changes: 0 additions & 27 deletions src/RenderingBoundary.tsx

This file was deleted.

10 changes: 0 additions & 10 deletions src/SuspenseBoundary.tsx

This file was deleted.

24 changes: 24 additions & 0 deletions src/hydrate-atoms/HydrationBoundary.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use client';

import type { PropsWithChildren } from 'react';
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,
options,
}: PropsWithChildren<{
hydrateAtoms: InferAtomTuples<T>;
options?: HydrateAtomOptions | undefined;
}>) {
useHydrateAtoms(hydrateAtoms, options);

return <>{children}</>;
}
2 changes: 2 additions & 0 deletions src/hydrate-atoms/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './use-hydrate-atoms.js';
export * from './HydrationBoundary.js';
18 changes: 18 additions & 0 deletions src/hydrate-atoms/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { createStore, WritableAtom } from 'jotai';

export type Store = ReturnType<typeof createStore>;

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

export type InferAtomTuples<T> = {
[K in keyof T]: T[K] extends readonly [infer A, ...unknown[]]
? A extends WritableAtom<unknown, infer Args, unknown>
? readonly [A, ...Args]
: T[K]
: never;
};

export type HydrateAtomOptions = {
store?: Store | undefined;
enableReHydrate?: boolean | undefined;
};
44 changes: 44 additions & 0 deletions src/hydrate-atoms/use-hydrate-atoms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { atom, useStore } from 'jotai';
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>, options?: HydrateAtomOptions) {
const isHydratedRef = useRef(false);
const lastHydrateAtoms = useRef(hydrateAtoms);
const store = useStore(
options?.store != null ? { store: options?.store } : undefined,
);

const hydrate = useCallback(() => {
store.set(isHydratingPrimitiveAtom, true);
for (const [atom, ...args] of hydrateAtoms) {
store.set(atom, ...args);
}
store.set(isHydratingPrimitiveAtom, false);
isHydratedRef.current = true;
}, [store, hydrateAtoms]);

if (!isHydratedRef.current) {
hydrate();
}

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

const isHydratingPrimitiveAtom = atom(false);

export const isHydratingAtom = atom((get) => get(isHydratingPrimitiveAtom));
4 changes: 1 addition & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
export * from './HydrationBoundary.js';
export * from './RenderingBoundary.js';
export * from './SuspenseBoundary.js';
export * from './hydrate-atoms/index.js';

0 comments on commit 05be6e5

Please sign in to comment.