snapshot of https://github.com/TanStack/query.git (main, 2026-09-16; blobs > 131072B omitted)
This commit is contained in:
307
packages/react-query-next-experimental/CHANGELOG.md
Normal file
307
packages/react-query-next-experimental/CHANGELOG.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# @tanstack/react-query-next-experimental
|
||||
|
||||
## 5.102.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.102.8
|
||||
|
||||
## 5.102.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.102.7
|
||||
|
||||
## 5.102.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ac2b612`](https://github.com/TanStack/query/commit/ac2b61230ea35b90b177ba35dc030598bac9c9a6)]:
|
||||
- @tanstack/react-query@5.102.6
|
||||
|
||||
## 5.102.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.102.5
|
||||
|
||||
## 5.102.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.102.4
|
||||
|
||||
## 5.102.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.102.3
|
||||
|
||||
## 5.102.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.102.2
|
||||
|
||||
## 5.102.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.102.1
|
||||
|
||||
## 5.102.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`37127db`](https://github.com/TanStack/query/commit/37127dbe479a4892dbbe28ac8ceabf8832b5f1a3), [`6e3d521`](https://github.com/TanStack/query/commit/6e3d521fe54f78624e53c1c6f9cadd678504bee8), [`294d4e6`](https://github.com/TanStack/query/commit/294d4e62c4f7d674574a4903eef2a1bc3dd1413b), [`cb6c9d3`](https://github.com/TanStack/query/commit/cb6c9d3725db0fed94fb5133820e41b7c326d2ef), [`2215bb0`](https://github.com/TanStack/query/commit/2215bb031139cdc8a84751b37a485c38ca9d2b6e), [`1ef4208`](https://github.com/TanStack/query/commit/1ef42087c9a266c2137d2ef645cbcc662f60ac93), [`fb6c3fa`](https://github.com/TanStack/query/commit/fb6c3fabda4cb6b291cccc6651ed88a7db901915), [`8834267`](https://github.com/TanStack/query/commit/88342670eca6e4949416aab832b1f81cc7b881f8), [`b866a95`](https://github.com/TanStack/query/commit/b866a95adde7e8465462526df5870ebc12340b36), [`e546d03`](https://github.com/TanStack/query/commit/e546d03bef116c66a05dbf42ccfd70b6d8600a8f), [`e674826`](https://github.com/TanStack/query/commit/e6748265c86294704f6c872e6f435d9ec5a92b28)]:
|
||||
- @tanstack/react-query@5.102.0
|
||||
|
||||
## 5.101.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.101.4
|
||||
|
||||
## 5.101.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.101.3
|
||||
|
||||
## 5.101.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.101.2
|
||||
|
||||
## 5.101.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.101.1
|
||||
|
||||
## 5.101.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#10857](https://github.com/TanStack/query/pull/10857) [`7cf5923`](https://github.com/TanStack/query/commit/7cf5923308fb91f3eff0fe952d8c64676e2bdad7) - fix(react-query-next-experimental): replace deprecated 'isServer' with 'environmentManager.isServer()'
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.101.0
|
||||
|
||||
## 5.100.14
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`ed20b6d`](https://github.com/TanStack/query/commit/ed20b6d7541c908033acfcad92b0cd112930d1c3)]:
|
||||
- @tanstack/react-query@5.100.14
|
||||
|
||||
## 5.100.13
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.13
|
||||
|
||||
## 5.100.12
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.12
|
||||
|
||||
## 5.100.11
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.11
|
||||
|
||||
## 5.100.10
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.10
|
||||
|
||||
## 5.100.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.9
|
||||
|
||||
## 5.100.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.8
|
||||
|
||||
## 5.100.7
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.7
|
||||
|
||||
## 5.100.6
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.6
|
||||
|
||||
## 5.100.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.5
|
||||
|
||||
## 5.100.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.4
|
||||
|
||||
## 5.100.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies [[`f85d825`](https://github.com/TanStack/query/commit/f85d825e02efbbff02e2081528ed28f5e5382f7a)]:
|
||||
- @tanstack/react-query@5.100.3
|
||||
|
||||
## 5.100.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.2
|
||||
|
||||
## 5.100.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.1
|
||||
|
||||
## 5.100.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.100.0
|
||||
|
||||
## 5.99.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.99.2
|
||||
|
||||
## 5.99.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.99.1
|
||||
|
||||
## 5.99.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.99.0
|
||||
|
||||
## 5.98.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.98.0
|
||||
|
||||
## 5.97.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.97.0
|
||||
|
||||
## 5.96.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.96.2
|
||||
|
||||
## 5.96.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.96.1
|
||||
|
||||
## 5.96.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.96.0
|
||||
|
||||
## 5.95.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.95.2
|
||||
|
||||
## 5.95.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.95.1
|
||||
|
||||
## 5.95.0
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Updated dependencies []:
|
||||
- @tanstack/react-query@5.95.0
|
||||
|
||||
## 5.94.5
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix(\*): resolve issue about excluded build directory ([#10312](https://github.com/TanStack/query/pull/10312))
|
||||
|
||||
- Updated dependencies [[`4b6536d`](https://github.com/TanStack/query/commit/4b6536dfce99036f4e37f52943c6fed3ad0e0a18)]:
|
||||
- @tanstack/react-query@5.94.5
|
||||
|
||||
## 5.94.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- chore: fixed version ([#10064](https://github.com/TanStack/query/pull/10064))
|
||||
|
||||
- Updated dependencies [[`4c75210`](https://github.com/TanStack/query/commit/4c75210ce8235fe3d39b67e1029eff11278927cc)]:
|
||||
- @tanstack/react-query@5.94.4
|
||||
|
||||
## 5.91.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- feat(react-query-next-experimental): support Next.js 16 ([#9868](https://github.com/TanStack/query/pull/9868))
|
||||
22
packages/react-query-next-experimental/eslint.config.js
Normal file
22
packages/react-query-next-experimental/eslint.config.js
Normal file
@@ -0,0 +1,22 @@
|
||||
// @ts-check
|
||||
|
||||
import pluginReact from '@eslint-react/eslint-plugin'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import rootConfig from './root.eslint.config.js'
|
||||
|
||||
export default [
|
||||
...rootConfig,
|
||||
// @ts-expect-error wtf
|
||||
...reactHooks.configs['recommended-latest'],
|
||||
{
|
||||
files: ['**/*.{ts,tsx}'],
|
||||
...pluginReact.configs.recommended,
|
||||
rules: {
|
||||
'@eslint-react/no-context-provider': 'off', // We need to be React 18 compatible
|
||||
'react-hooks/exhaustive-deps': 'error',
|
||||
'react-hooks/rules-of-hooks': 'error',
|
||||
'react-hooks/unsupported-syntax': 'error',
|
||||
'react-hooks/incompatible-library': 'error',
|
||||
},
|
||||
},
|
||||
]
|
||||
68
packages/react-query-next-experimental/package.json
Normal file
68
packages/react-query-next-experimental/package.json
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"name": "@tanstack/react-query-next-experimental",
|
||||
"version": "5.102.8",
|
||||
"description": "Hydration utils for React Query in the NextJs app directory",
|
||||
"author": "tannerlinsley",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/TanStack/query.git",
|
||||
"directory": "packages/react-query-next-experimental"
|
||||
},
|
||||
"homepage": "https://tanstack.com/query",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/tannerlinsley"
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "premove ./build ./coverage ./dist-ts ./.cache/test-types",
|
||||
"compile": "tsc --project tsconfig.json",
|
||||
"test:eslint": "eslint --concurrency=auto ./src",
|
||||
"test:types": "npm-run-all --serial test:types:*",
|
||||
"test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts56 --tsBuildInfoFile .cache/test-types/ts56.tsbuildinfo",
|
||||
"test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts57 --tsBuildInfoFile .cache/test-types/ts57.tsbuildinfo",
|
||||
"test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts58 --tsBuildInfoFile .cache/test-types/ts58.tsbuildinfo",
|
||||
"test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js --project tsconfig.legacy.json --outDir .cache/test-types/ts59 --tsBuildInfoFile .cache/test-types/ts59.tsbuildinfo",
|
||||
"test:types:tscurrent": "tsc --project tsconfig.json --outDir .cache/test-types/tscurrent --tsBuildInfoFile .cache/test-types/tscurrent.tsbuildinfo",
|
||||
"test:types:ts70": "node ../../node_modules/typescript70/lib/tsc.js --project tsconfig.json --outDir .cache/test-types/ts70 --tsBuildInfoFile .cache/test-types/ts70.tsbuildinfo",
|
||||
"test:build": "publint --strict && attw --pack",
|
||||
"build": "tsdown --tsconfig tsconfig.prod.json"
|
||||
},
|
||||
"type": "module",
|
||||
"types": "build/legacy/index.d.ts",
|
||||
"main": "build/legacy/index.cjs",
|
||||
"module": "build/legacy/index.js",
|
||||
"exports": {
|
||||
".": {
|
||||
"@tanstack/custom-condition": "./src/index.ts",
|
||||
"import": {
|
||||
"types": "./build/modern/index.d.ts",
|
||||
"default": "./build/modern/index.js"
|
||||
},
|
||||
"require": {
|
||||
"types": "./build/modern/index.d.cts",
|
||||
"default": "./build/modern/index.cjs"
|
||||
}
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"build",
|
||||
"src",
|
||||
"!src/__tests__"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@tanstack/react-query": "workspace:*",
|
||||
"@types/react": "^19.2.7",
|
||||
"@vitejs/plugin-react": "^4.3.4",
|
||||
"next": "^16.0.1",
|
||||
"npm-run-all2": "^5.0.0",
|
||||
"react": "^19.2.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tanstack/react-query": "workspace:^",
|
||||
"next": "^13 || ^14 || ^15 || ^16",
|
||||
"react": "^18 || ^19"
|
||||
}
|
||||
}
|
||||
1
packages/react-query-next-experimental/root.eslint.config.js
Symbolic link
1
packages/react-query-next-experimental/root.eslint.config.js
Symbolic link
@@ -0,0 +1 @@
|
||||
../../eslint.config.js
|
||||
1
packages/react-query-next-experimental/root.tsdown.config.js
Symbolic link
1
packages/react-query-next-experimental/root.tsdown.config.js
Symbolic link
@@ -0,0 +1 @@
|
||||
../../scripts/getTsdownConfig.js
|
||||
@@ -0,0 +1,192 @@
|
||||
'use client'
|
||||
|
||||
import { environmentManager } from '@tanstack/react-query'
|
||||
import { useServerInsertedHTML } from 'next/navigation'
|
||||
import * as React from 'react'
|
||||
import { htmlEscapeJsonString } from './htmlescape'
|
||||
|
||||
const serializedSymbol = Symbol('serialized')
|
||||
|
||||
interface DataTransformer {
|
||||
serialize: (object: any) => any
|
||||
deserialize: (object: any) => any
|
||||
}
|
||||
|
||||
type Serialized<TData> = unknown & {
|
||||
[serializedSymbol]: TData
|
||||
}
|
||||
|
||||
interface TypedDataTransformer<TData> {
|
||||
serialize: (obj: TData) => Serialized<TData>
|
||||
deserialize: (obj: Serialized<TData>) => TData
|
||||
}
|
||||
|
||||
interface HydrationStreamContext<TShape> {
|
||||
id: string
|
||||
stream: {
|
||||
/**
|
||||
* **Server method**
|
||||
* Push a new entry to the stream
|
||||
* Will be ignored on the client
|
||||
*/
|
||||
push: (...shape: Array<TShape>) => void
|
||||
}
|
||||
}
|
||||
|
||||
export interface HydrationStreamProviderProps<TShape> {
|
||||
children: React.ReactNode
|
||||
/**
|
||||
* Optional transformer to serialize/deserialize the data
|
||||
* Example devalue, superjson et al
|
||||
*/
|
||||
transformer?: DataTransformer
|
||||
/**
|
||||
* **Client method**
|
||||
* Called in the browser when new entries are received
|
||||
*/
|
||||
onEntries: (entries: Array<TShape>) => void
|
||||
/**
|
||||
* **Server method**
|
||||
* onFlush is called on the server when the cache is flushed
|
||||
*/
|
||||
onFlush?: () => Array<TShape>
|
||||
/**
|
||||
* A nonce that'll allow the inline script to be executed when Content Security Policy is enforced
|
||||
*/
|
||||
nonce?: string
|
||||
}
|
||||
|
||||
export function createHydrationStreamProvider<TShape>() {
|
||||
const context = React.createContext<HydrationStreamContext<TShape>>(
|
||||
null as any,
|
||||
)
|
||||
/**
|
||||
|
||||
* 1. (Happens on server): `useServerInsertedHTML()` is called **on the server** whenever a `Suspense`-boundary completes
|
||||
* - This means that we might have some new entries in the cache that needs to be flushed
|
||||
* - We pass these to the client by inserting a `<script>`-tag where we do `window[id].push(serializedVersionOfCache)`
|
||||
* 2. (Happens in browser) In `useEffect()`:
|
||||
* - We check if `window[id]` is set to an array and call `push()` on all the entries which will call `onEntries()` with the new entries
|
||||
* - We replace `window[id]` with a `push()`-method that will be called whenever new entries are received
|
||||
**/
|
||||
function UseClientHydrationStreamProvider(props: {
|
||||
children: React.ReactNode
|
||||
/**
|
||||
* Optional transformer to serialize/deserialize the data
|
||||
* Example devalue, superjson et al
|
||||
*/
|
||||
transformer?: DataTransformer
|
||||
/**
|
||||
* **Client method**
|
||||
* Called in the browser when new entries are received
|
||||
*/
|
||||
onEntries: (entries: Array<TShape>) => void
|
||||
/**
|
||||
* **Server method**
|
||||
* onFlush is called on the server when the cache is flushed
|
||||
*/
|
||||
onFlush?: () => Array<TShape>
|
||||
/**
|
||||
* A nonce that'll allow the inline script to be executed when Content Security Policy is enforced
|
||||
*/
|
||||
nonce?: string
|
||||
}) {
|
||||
// unique id for the cache provider
|
||||
const id = `__RQ${React.useId()}`
|
||||
const idJSON = htmlEscapeJsonString(JSON.stringify(id))
|
||||
|
||||
const [transformer] = React.useState(
|
||||
() =>
|
||||
(props.transformer ?? {
|
||||
// noop
|
||||
serialize: (obj: any) => obj,
|
||||
deserialize: (obj: any) => obj,
|
||||
}) as unknown as TypedDataTransformer<TShape>,
|
||||
)
|
||||
|
||||
// <server stuff>
|
||||
const [stream] = React.useState<Array<TShape>>(() => {
|
||||
if (!environmentManager.isServer()) {
|
||||
return {
|
||||
push() {
|
||||
// no-op on the client
|
||||
},
|
||||
} as unknown as Array<TShape>
|
||||
}
|
||||
return []
|
||||
})
|
||||
const count = React.useRef(0)
|
||||
useServerInsertedHTML(() => {
|
||||
// This only happens on the server
|
||||
stream.push(...(props.onFlush?.() ?? []))
|
||||
|
||||
if (!stream.length) {
|
||||
return null
|
||||
}
|
||||
// console.log(`pushing ${stream.length} entries`)
|
||||
const serializedCacheArgs = stream
|
||||
.map((entry) => transformer.serialize(entry))
|
||||
.map((entry) => JSON.stringify(entry))
|
||||
.join(',')
|
||||
|
||||
// Flush stream
|
||||
// eslint-disable-next-line react-hooks/immutability
|
||||
stream.length = 0
|
||||
|
||||
const html: Array<string> = [
|
||||
`window[${idJSON}] = window[${idJSON}] || [];`,
|
||||
`window[${idJSON}].push(${htmlEscapeJsonString(serializedCacheArgs)});`,
|
||||
]
|
||||
return (
|
||||
<script
|
||||
key={count.current++}
|
||||
nonce={props.nonce}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: html.join(''),
|
||||
}}
|
||||
/>
|
||||
)
|
||||
})
|
||||
// </server stuff>
|
||||
|
||||
// <client stuff>
|
||||
// Setup and run the onEntries handler on the client only, but do it during
|
||||
// the initial render so children have access to the data immediately
|
||||
// This is important to avoid the client suspending during the initial render
|
||||
// if the data has not yet been hydrated.
|
||||
if (!environmentManager.isServer()) {
|
||||
const win = window as any
|
||||
if (!win[id]?.initialized) {
|
||||
// Client: consume cache:
|
||||
const onEntries = (...serializedEntries: Array<Serialized<TShape>>) => {
|
||||
const entries = serializedEntries.map((serialized) =>
|
||||
transformer.deserialize(serialized),
|
||||
)
|
||||
props.onEntries(entries)
|
||||
}
|
||||
|
||||
const winStream: Array<Serialized<TShape>> = win[id] ?? []
|
||||
|
||||
onEntries(...winStream)
|
||||
|
||||
// eslint-disable-next-line react-hooks/immutability
|
||||
win[id] = {
|
||||
initialized: true,
|
||||
push: onEntries,
|
||||
}
|
||||
}
|
||||
}
|
||||
// </client stuff>
|
||||
|
||||
return (
|
||||
<context.Provider value={{ stream, id }}>
|
||||
{props.children}
|
||||
</context.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
Provider: UseClientHydrationStreamProvider,
|
||||
context,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
'use client'
|
||||
|
||||
import {
|
||||
defaultShouldDehydrateQuery,
|
||||
dehydrate,
|
||||
environmentManager,
|
||||
hydrate,
|
||||
useQueryClient,
|
||||
} from '@tanstack/react-query'
|
||||
import * as React from 'react'
|
||||
import { createHydrationStreamProvider } from './HydrationStreamProvider'
|
||||
import type { HydrationStreamProviderProps } from './HydrationStreamProvider'
|
||||
import type {
|
||||
DehydrateOptions,
|
||||
DehydratedState,
|
||||
HydrateOptions,
|
||||
QueryClient,
|
||||
} from '@tanstack/react-query'
|
||||
|
||||
const stream = createHydrationStreamProvider<DehydratedState>()
|
||||
|
||||
/**
|
||||
* This component is responsible for:
|
||||
* - hydrating the query client on the server
|
||||
* - dehydrating the query client on the server
|
||||
*/
|
||||
export function ReactQueryStreamedHydration(props: {
|
||||
children: React.ReactNode
|
||||
queryClient?: QueryClient
|
||||
nonce?: string
|
||||
options?: {
|
||||
hydrate?: HydrateOptions
|
||||
dehydrate?: DehydrateOptions
|
||||
}
|
||||
transformer?: HydrationStreamProviderProps<DehydratedState>['transformer']
|
||||
}) {
|
||||
const queryClient = useQueryClient(props.queryClient)
|
||||
|
||||
/**
|
||||
* We need to track which queries were added/updated during the render
|
||||
*/
|
||||
const [trackedKeys] = React.useState(() => new Set<string>())
|
||||
|
||||
// <server only>
|
||||
if (environmentManager.isServer()) {
|
||||
// Do we need to care about unsubscribing? I don't think so to be honest
|
||||
queryClient.getQueryCache().subscribe((event) => {
|
||||
switch (event.type) {
|
||||
case 'added':
|
||||
case 'updated':
|
||||
// console.log('tracking', event.query.queryHash, 'b/c of a', event.type)
|
||||
trackedKeys.add(event.query.queryHash)
|
||||
}
|
||||
})
|
||||
}
|
||||
// </server only>
|
||||
|
||||
return (
|
||||
<stream.Provider
|
||||
// Happens on server:
|
||||
onFlush={() => {
|
||||
/**
|
||||
* Dehydrated state of the client where we only include the queries that were added/updated since the last flush
|
||||
*/
|
||||
const shouldDehydrate =
|
||||
props.options?.dehydrate?.shouldDehydrateQuery ??
|
||||
defaultShouldDehydrateQuery
|
||||
|
||||
const dehydratedState = dehydrate(queryClient, {
|
||||
...props.options?.dehydrate,
|
||||
shouldDehydrateQuery(query) {
|
||||
return trackedKeys.has(query.queryHash) && shouldDehydrate(query)
|
||||
},
|
||||
})
|
||||
trackedKeys.clear()
|
||||
|
||||
if (!dehydratedState.queries.length) {
|
||||
return []
|
||||
}
|
||||
|
||||
return [dehydratedState]
|
||||
}}
|
||||
// Happens in browser:
|
||||
onEntries={(entries) => {
|
||||
for (const hydratedState of entries) {
|
||||
hydrate(queryClient, hydratedState, props.options?.hydrate)
|
||||
}
|
||||
}}
|
||||
// Handle BigInts etc using superjson
|
||||
transformer={props.transformer}
|
||||
nonce={props.nonce}
|
||||
>
|
||||
{props.children}
|
||||
</stream.Provider>
|
||||
)
|
||||
}
|
||||
24
packages/react-query-next-experimental/src/htmlescape.ts
Normal file
24
packages/react-query-next-experimental/src/htmlescape.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
// --------------------------------------------------------------------------------
|
||||
//
|
||||
// copied from
|
||||
// https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts
|
||||
// License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md
|
||||
//
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// This utility is based on https://github.com/zertosh/htmlescape
|
||||
// License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE
|
||||
|
||||
const ESCAPE_LOOKUP: Record<string, string> = {
|
||||
'&': '\\u0026',
|
||||
'>': '\\u003e',
|
||||
'<': '\\u003c',
|
||||
'\u2028': '\\u2028',
|
||||
'\u2029': '\\u2029',
|
||||
}
|
||||
|
||||
export const ESCAPE_REGEX = /[&><\u2028\u2029]/g
|
||||
|
||||
export function htmlEscapeJsonString(str: string): string {
|
||||
return str.replace(ESCAPE_REGEX, (match) => ESCAPE_LOOKUP[match]!)
|
||||
}
|
||||
1
packages/react-query-next-experimental/src/index.ts
Normal file
1
packages/react-query-next-experimental/src/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { ReactQueryStreamedHydration } from './ReactQueryStreamedHydration'
|
||||
10
packages/react-query-next-experimental/tsconfig.json
Normal file
10
packages/react-query-next-experimental/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist-ts",
|
||||
"rootDir": ".",
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"include": ["src", "*.config.ts", "*.config.js", "package.json"],
|
||||
"references": [{ "path": "../react-query" }]
|
||||
}
|
||||
10
packages/react-query-next-experimental/tsconfig.legacy.json
Normal file
10
packages/react-query-next-experimental/tsconfig.legacy.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"outDir": "./dist-ts/legacy"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["src/__tests__"],
|
||||
"references": [{ "path": "../react-query" }]
|
||||
}
|
||||
10
packages/react-query-next-experimental/tsconfig.prod.json
Normal file
10
packages/react-query-next-experimental/tsconfig.prod.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"incremental": false,
|
||||
"composite": false,
|
||||
"rootDir": "../../"
|
||||
},
|
||||
"include": ["src"],
|
||||
"exclude": ["src/__tests__"]
|
||||
}
|
||||
7
packages/react-query-next-experimental/tsdown.config.ts
Normal file
7
packages/react-query-next-experimental/tsdown.config.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import { defineConfig } from 'tsdown'
|
||||
import { legacyConfig, modernConfig } from './root.tsdown.config.js'
|
||||
|
||||
export default defineConfig([
|
||||
modernConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),
|
||||
legacyConfig({ entry: ['src/*.ts', 'src/*.tsx'] }),
|
||||
])
|
||||
17
packages/react-query-next-experimental/vite.config.ts
Normal file
17
packages/react-query-next-experimental/vite.config.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
// fix from https://github.com/vitest-dev/vitest/issues/6992#issuecomment-2509408660
|
||||
resolve: {
|
||||
conditions: ['@tanstack/custom-condition'],
|
||||
},
|
||||
environments: {
|
||||
ssr: {
|
||||
resolve: {
|
||||
conditions: ['@tanstack/custom-condition'],
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user