-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(react-query-v4): react-query-next-experimental (#1161)
# Overview #1155 Adds a streaming without prefetching feature that brings the [react-query-next-experimental](https://tanstack.com/query/latest/docs/framework/react/guides/advanced-ssr#experimental-streaming-without-prefetching-in-nextjs) feature available in react-query v5 to v4 - [x] Add a default implementation - HydrationStreamProvider - ReactQueryStreamedHydration - [x] ~~Test working well~~ continue with the follow-up. <!-- A clear and concise description of what this pr is about. --> ## PR Checklist - [x] I did below actions if need 1. I read the [Contributing Guide](https://github.com/toss/suspensive/blob/main/CONTRIBUTING.md) 2. I added documents and tests. --------- Co-authored-by: Jonghyeon Ko <[email protected]> Co-authored-by: Jonghyeon Ko <[email protected]>
- Loading branch information
1 parent
c179a56
commit 29205c7
Showing
47 changed files
with
1,117 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@suspensive/react-query-next-experimental-4": patch | ||
--- | ||
|
||
feat(react-query-next-experimental): react-query-next-experimental |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
9 changes: 9 additions & 0 deletions
9
examples/react-query-next-experimental-4-example/.eslintrc.cjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
/** @type {import('eslint').Linter.Config} */ | ||
module.exports = { | ||
root: true, | ||
extends: ['@suspensive/eslint-config/react-ts', 'plugin:@next/next/recommended'], | ||
parserOptions: { | ||
tsconfigRootDir: __dirname, | ||
project: 'tsconfig.json', | ||
}, | ||
} |
35 changes: 35 additions & 0 deletions
35
examples/react-query-next-experimental-4-example/.gitignore
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
8 changes: 8 additions & 0 deletions
8
examples/react-query-next-experimental-4-example/next.config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/** @type {import('next').NextConfig} */ | ||
const nextConfig = { | ||
experimental: { | ||
typedRoutes: true, | ||
}, | ||
} | ||
|
||
module.exports = nextConfig |
31 changes: 31 additions & 0 deletions
31
examples/react-query-next-experimental-4-example/package.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
{ | ||
"name": "@suspensive/react-query-next-experimental-4-example", | ||
"version": "0.0.0", | ||
"private": true, | ||
"scripts": { | ||
"build": "next build", | ||
"ci:eslint": "next lint", | ||
"ci:type": "tsc --noEmit", | ||
"dev": "next dev -p 4100", | ||
"start": "next start -p 4100" | ||
}, | ||
"dependencies": { | ||
"@suspensive/react": "workspace:*", | ||
"@suspensive/react-query-4": "workspace:*", | ||
"@suspensive/react-query-next-experimental-4": "workspace:*", | ||
"@tanstack/react-query": "^4.36.1", | ||
"@tanstack/react-query-devtools": "^4.36.1", | ||
"next": "^14.2.3", | ||
"react": "^18.3.1", | ||
"react-dom": "^18.3.1", | ||
"tailwindcss": "^3.4.4" | ||
}, | ||
"devDependencies": { | ||
"@next/eslint-plugin-next": "^14.2.3", | ||
"@suspensive/eslint-config": "workspace:*", | ||
"@types/react": "^18.3.3", | ||
"@types/react-dom": "^18.3.0", | ||
"autoprefixer": "^10.4.19", | ||
"postcss": "^8.4.38" | ||
} | ||
} |
6 changes: 6 additions & 0 deletions
6
examples/react-query-next-experimental-4-example/postcss.config.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = { | ||
plugins: { | ||
tailwindcss: {}, | ||
autoprefixer: {}, | ||
}, | ||
} |
1 change: 1 addition & 0 deletions
1
examples/react-query-next-experimental-4-example/public/next.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions
1
examples/react-query-next-experimental-4-example/public/vercel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions
9
examples/react-query-next-experimental-4-example/src/app/api/text/route.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import { NextResponse } from 'next/server' | ||
|
||
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)) | ||
|
||
export async function GET(request: Request) { | ||
const ms = Number(new URL(request.url).searchParams.get('wait')) | ||
await sleep(ms) | ||
return NextResponse.json(`${new Date().toISOString()} success to get text waited after ${ms}ms`) | ||
} |
15 changes: 15 additions & 0 deletions
15
examples/react-query-next-experimental-4-example/src/app/components/Text.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
'use client' | ||
|
||
import { useSuspenseQuery } from '@suspensive/react-query-4' | ||
import { type ComponentProps, forwardRef } from 'react' | ||
import { query } from '~/query' | ||
|
||
export const Text = forwardRef<HTMLParagraphElement, ComponentProps<'p'> & { ms: number }>(({ ms, ...props }, ref) => { | ||
const { data: text } = useSuspenseQuery(query.text(ms)) | ||
return ( | ||
<p {...props} ref={ref}> | ||
result: {text} | ||
</p> | ||
) | ||
}) | ||
Text.displayName = 'Text' |
8 changes: 8 additions & 0 deletions
8
examples/react-query-next-experimental-4-example/src/app/components/Text2.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { type ComponentProps, forwardRef } from 'react' | ||
|
||
export const Text2 = forwardRef<HTMLParagraphElement, ComponentProps<'p'>>((props, ref) => ( | ||
<p {...props} ref={ref}> | ||
result: {props.children} | ||
</p> | ||
)) | ||
Text2.displayName = 'Text2' |
Binary file not shown.
27 changes: 27 additions & 0 deletions
27
examples/react-query-next-experimental-4-example/src/app/globals.css
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
|
||
:root { | ||
--foreground-rgb: 0, 0, 0; | ||
--background-start-rgb: 214, 219, 220; | ||
--background-end-rgb: 255, 255, 255; | ||
} | ||
|
||
@media (prefers-color-scheme: dark) { | ||
:root { | ||
--foreground-rgb: 255, 255, 255; | ||
--background-start-rgb: 0, 0, 0; | ||
--background-end-rgb: 0, 0, 0; | ||
} | ||
} | ||
|
||
body { | ||
color: rgb(var(--foreground-rgb)); | ||
background: linear-gradient( | ||
to bottom, | ||
transparent, | ||
rgb(var(--background-end-rgb)) | ||
) | ||
rgb(var(--background-start-rgb)); | ||
} |
17 changes: 17 additions & 0 deletions
17
examples/react-query-next-experimental-4-example/src/app/layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { Metadata } from 'next' | ||
import type { ReactNode } from 'react' | ||
import { Providers } from './providers' | ||
|
||
export const metadata: Metadata = { | ||
title: 'Next HTML Streaming with Suspense', | ||
} | ||
|
||
export default function RootLayout({ children }: { children: ReactNode }) { | ||
return ( | ||
<html lang="en"> | ||
<body> | ||
<Providers>{children}</Providers> | ||
</body> | ||
</html> | ||
) | ||
} |
89 changes: 89 additions & 0 deletions
89
examples/react-query-next-experimental-4-example/src/app/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
'use client' | ||
|
||
import { Suspense } from '@suspensive/react' | ||
import { SuspenseQuery } from '@suspensive/react-query-4' | ||
import { useQueryClient } from '@tanstack/react-query' | ||
import Link from 'next/link' | ||
import { Text } from '~/app/components/Text' | ||
import { Text2 } from '~/app/components/Text2' | ||
import { query } from '~/query' | ||
|
||
export default function Page() { | ||
const queryClient = useQueryClient() | ||
|
||
return ( | ||
<> | ||
<Link href="/test">to test page</Link> | ||
<Suspense> | ||
<Text ms={100} /> | ||
</Suspense> | ||
<Suspense> | ||
<Text ms={200} /> | ||
</Suspense> | ||
<Suspense> | ||
<Text ms={300} /> | ||
</Suspense> | ||
<Suspense> | ||
<Text ms={400} /> | ||
</Suspense> | ||
<Suspense> | ||
<Text ms={500} /> | ||
</Suspense> | ||
<Suspense> | ||
<Text ms={600} /> | ||
</Suspense> | ||
<Suspense> | ||
<Text ms={700} /> | ||
</Suspense> | ||
|
||
<button | ||
onClick={() => { | ||
queryClient.resetQueries() | ||
}} | ||
> | ||
resetQueries all | ||
</button> | ||
|
||
<button | ||
onClick={() => { | ||
queryClient.invalidateQueries(query.text(500)) | ||
}} | ||
> | ||
invalidate 500 | ||
</button> | ||
|
||
<button | ||
onClick={() => { | ||
queryClient.invalidateQueries(query.text(200)) | ||
}} | ||
> | ||
invalidate 200 | ||
</button> | ||
|
||
<fieldset> | ||
<legend> | ||
combined <code>Suspense</code>-container | ||
</legend> | ||
<Suspense> | ||
<Text ms={800} /> | ||
<Text ms={900} /> | ||
<Text ms={1000} /> | ||
</Suspense> | ||
</fieldset> | ||
|
||
<pre>{`Proposal: <SuspenseQuery /> Component`}</pre> | ||
{/* Need to proposal */} | ||
<ul> | ||
<Suspense> | ||
<SuspenseQuery {...query.text(1100)}>{({ data }) => <Text2>{data}</Text2>}</SuspenseQuery> | ||
</Suspense> | ||
<Suspense> | ||
<SuspenseQuery {...query.text(1200)}>{({ data }) => <Text2>{data}</Text2>}</SuspenseQuery> | ||
</Suspense> | ||
<Suspense> | ||
<SuspenseQuery {...query.text(1300)}>{({ data }) => <Text2>{data}</Text2>}</SuspenseQuery> | ||
</Suspense> | ||
</ul> | ||
</> | ||
) | ||
} |
37 changes: 37 additions & 0 deletions
37
examples/react-query-next-experimental-4-example/src/app/providers.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
'use client' | ||
|
||
import { Suspensive, SuspensiveProvider } from '@suspensive/react' | ||
import { ReactQueryStreamedHydration } from '@suspensive/react-query-next-experimental-4' | ||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query' | ||
import { ReactQueryDevtools } from '@tanstack/react-query-devtools' | ||
import { type ReactNode, useState } from 'react' | ||
|
||
export function Providers(props: { children: ReactNode }) { | ||
const [queryClient] = useState( | ||
() => | ||
new QueryClient({ | ||
defaultOptions: { | ||
queries: { | ||
staleTime: 5 * 1000, | ||
}, | ||
}, | ||
}) | ||
) | ||
const [suspensive] = useState( | ||
() => | ||
new Suspensive({ | ||
defaultProps: { | ||
suspense: { fallback: <div>loading...</div> }, | ||
}, | ||
}) | ||
) | ||
|
||
return ( | ||
<SuspensiveProvider value={suspensive}> | ||
<QueryClientProvider client={queryClient}> | ||
<ReactQueryStreamedHydration>{props.children}</ReactQueryStreamedHydration> | ||
<ReactQueryDevtools initialIsOpen={false} /> | ||
</QueryClientProvider> | ||
</SuspensiveProvider> | ||
) | ||
} |
10 changes: 10 additions & 0 deletions
10
examples/react-query-next-experimental-4-example/src/app/test/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import Link from 'next/link' | ||
|
||
export default function page() { | ||
return ( | ||
<div> | ||
page | ||
<Link href="/">to home page</Link> | ||
</div> | ||
) | ||
} |
21 changes: 21 additions & 0 deletions
21
examples/react-query-next-experimental-4-example/src/query/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { queryOptions } from '@suspensive/react-query-4' | ||
|
||
const baseURL = (() => { | ||
if (typeof window !== 'undefined') return '' | ||
if (process.env.NEXT_PUBLIC_STREAMING_HTML_URL) return `https://${process.env.NEXT_PUBLIC_STREAMING_HTML_URL}` | ||
return 'http://localhost:4100' | ||
})() | ||
|
||
export const query = { | ||
text: <TMs extends number>(ms: TMs) => | ||
queryOptions({ | ||
queryKey: ['query.text', ms], | ||
queryFn: () => | ||
fetch(`${baseURL}/api/text?wait=${ms}`, { | ||
cache: 'no-store', | ||
}).then( | ||
(res) => | ||
res.json() as unknown as `${ReturnType<Date['toISOString']>} success to get text waited after ${TMs}ms` | ||
), | ||
}), | ||
} |
Oops, something went wrong.