Skip to content

Commit

Permalink
remove ssr provider
Browse files Browse the repository at this point in the history
  • Loading branch information
akkadaska committed Jan 4, 2025
1 parent 4f2325b commit e32a21d
Show file tree
Hide file tree
Showing 7 changed files with 35 additions and 95 deletions.
79 changes: 32 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

**jotai-ssr** is a utility library for [Jotai](https://jotai.org/) to facilitate server-side rendering (SSR). It provides helpers for:

- Creating an **isolated store per request** (to avoid data leak between users).
- **Hydrating** atom values from server to client (and optionally re-hydrating).
- Handling SSR scenarios, including **React Server Components** and soft navigations in frameworks like Next.js, Remix, and Waku.

Expand All @@ -13,9 +12,7 @@ This library extends or wraps the existing Jotai SSR utilities to provide a more
## Table of Contents

1. [Installation](#installation)
2. [Creating a Safe Store for Each Request](#creating-a-safe-store-for-each-request)
1. [`useCreateStore`](#usecreatestore)
2. [`SSRProvider`](#ssrprovider)
2. [Creating a Safe Store for Each Request](#creating-a-safe-store-for-each-request)
3. [Hydration](#hydration)
1. [What is Hydration?](#what-is-hydration)
2. [How to Hydrate an Atom](#how-to-hydrate-an-atom)
Expand Down Expand Up @@ -43,64 +40,52 @@ pnpm add jotai-ssr

When using Jotai in an SSR environment, **you must ensure each request has its own store**. Relying on a shared, global store (e.g. `defaultStore`) across requests can lead to data leakage between different users.

### Using the `useCreateStore` Hook

If you create a store manually, you typically do it like this in a Client Component:

```tsx
'use client';
import { createStore, Provider } from 'jotai';
import { useState } from 'react';

const Page = () => {
// Ensure a new store is created per request
const [store] = useState(() => createStore());
return <Provider store={store}>{/* your content */}</Provider>;
};
```

**jotai-ssr** offers a convenient `useCreateStore` hook to simplify this pattern:
To create an isolated store per request, you should use `Provider` for each layout or page that uses Jotai like so:

```tsx
'use client';
import { Provider } from 'jotai';
import { useCreateStore } from 'jotai-ssr';

const Page = () => {
const store = useCreateStore();
return <Provider store={store}>{/* your content */}</Provider>;
return (
<Provider>{/* Your content */}</Provider>
);
};
```

> **Note:** `useCreateStore` internally uses `useState`, so the component that calls `useCreateStore` must be a React Client Component (i.e., have the `'use client'` directive if you're in an RSC setup).
If you need to pass a custom store to the `Provider`, you can do so in one of the following ways:

### Using the `SSRProvider`
1. **Using useState**

Alternatively, you can use the higher-level `SSRProvider` component from **jotai-ssr**. It can be used in either a React Client Component or a React Server Component:
```tsx
'use client';

```tsx
import { SSRProvider } from 'jotai-ssr';
import { createStore, Provider } from 'jotai';
import { useState } from 'react';

const Page = () => {
return <SSRProvider>{/* your content */}</SSRProvider>;
};
```
const Page = () => {
const [store] = useState(() => createStore());
return <Provider store={store}>{/* your content */}</Provider>;
};
```

Internally, `SSRProvider` will create an isolated store for each request. You can also supply your own store:
2. **Using useRef**

```tsx
'use client';
import { SSRProvider, useCreateStore } from 'jotai-ssr';
```tsx
'use client';

import { createStore, Provider } from 'jotai';
import { useRef } from 'react';

const Page = () => {
const storeRef = useRef(undefined);
if (!storeRef.current) {
storeRef.current = createStore();
}
return <Provider store={storeRef.current}>{/* your content */}</Provider>;
};
```

const Page = () => {
const store = useCreateStore();
return (
<SSRProvider store={store}>
{/* your content */}
</SSRProvider>
);
};
```
Both approaches ensure a new store instance is created for each request, preventing data from leaking between different users.

---

Expand Down
5 changes: 3 additions & 2 deletions src/hydrate-atoms/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { WritableAtom } from 'jotai';
import type { Store } from '../shared.js';
import type { createStore, WritableAtom } from 'jotai';

export type Store = ReturnType<typeof createStore>;

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

Expand Down
1 change: 0 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export * from './hydrate-atoms/index.js';
export * from './ssr-provider/index.js';
3 changes: 0 additions & 3 deletions src/shared.ts

This file was deleted.

33 changes: 0 additions & 33 deletions src/ssr-provider/SSRProvider.tsx

This file was deleted.

2 changes: 0 additions & 2 deletions src/ssr-provider/index.ts

This file was deleted.

7 changes: 0 additions & 7 deletions src/ssr-provider/use-create-store.ts

This file was deleted.

0 comments on commit e32a21d

Please sign in to comment.