Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: react-query-next-experimental package #5598

Merged
merged 32 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
42c4613
chore: fix a copy-paste error
TkDodo Jun 17, 2023
5777555
chore: bootstrap package
TkDodo Jun 17, 2023
f6344ca
chore: setup package
TkDodo Jun 17, 2023
526c2e3
chore: allow passing with no tests
TkDodo Jun 17, 2023
dd7233c
fix: remove 'use client' from index bundle
TkDodo Jun 17, 2023
6ddb1ca
chore: cleanup copy/paste error
TkDodo Jun 17, 2023
2d7265b
chore: fix prettier
TkDodo Jun 17, 2023
c428e49
refactor: replace ref with direct props access
TkDodo Jun 18, 2023
40efb37
fix: do not write to refs during render
TkDodo Jun 18, 2023
7336754
refactor: inline function into useEffect to avoid useCallback
TkDodo Jun 18, 2023
c5169c5
fix: eslint no-shadow
TkDodo Jun 18, 2023
fede312
refactor: namespace id
TkDodo Jun 18, 2023
9ce9513
refactor: removed pointless check
TkDodo Jun 18, 2023
a83ca67
fix: set to empty array on cleanup
TkDodo Jun 18, 2023
cb6d33f
Merge branch 'alpha' into feature/suspense
TkDodo Jun 18, 2023
17edfd5
Merge branch 'alpha' into feature/suspense
TkDodo Jun 19, 2023
09ac023
fix: adapt for v5 changes
TkDodo Jun 19, 2023
ed8baa5
chore: fix build
TkDodo Jun 19, 2023
6ebe4f3
docs: add streaming example
TkDodo Jun 19, 2023
595c732
chore: fix outdated lockfile
TkDodo Jun 19, 2023
bd75087
chore: fix prettier
TkDodo Jun 19, 2023
c6727fe
Merge branch 'alpha' into feature/suspense
TkDodo Jun 23, 2023
83ec6f6
Merge branch 'alpha' into feature/suspense
TkDodo Jun 25, 2023
4ef87c1
refactor: remove isSubscribed ref
TkDodo Jun 25, 2023
ba57ad8
refactor: re-arrange comment
TkDodo Jun 25, 2023
acf0da6
chore: remove comments
TkDodo Jun 25, 2023
137433d
Merge branch 'alpha' into feature/suspense
TkDodo Jun 27, 2023
63c2891
chore: fix broken lock file
TkDodo Jun 27, 2023
2d45542
Merge branch 'alpha' into feature/suspense
TkDodo Jun 27, 2023
4cad0d4
Merge branch 'alpha' into feature/suspense
TkDodo Jun 27, 2023
9d67d8b
feat: allow customization of hydrate / dehydrate options
TkDodo Jun 27, 2023
5bf15c2
Merge branch 'alpha' into feature/suspense
TkDodo Jul 14, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions babel.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ module.exports = {
'./packages/react-query/**',
'./packages/react-query-devtools/**',
'./packages/react-query-persist-client/**',
'./packages/react-query-next-experimental/**',
],
presets: ['@babel/react'],
},
Expand Down
4 changes: 4 additions & 0 deletions docs/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,10 @@
"label": "Next.js",
"to": "react/examples/react/nextjs"
},
{
"label": "Next.js app with streaming",
"to": "react/examples/react/nextjs-suspense-streaming"
},
{
"label": "React Native",
"to": "react/examples/react/react-native"
Expand Down
17 changes: 17 additions & 0 deletions examples/react/nextjs-suspense-streaming/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
eslint: {
ignoreDuringBuilds: true,
},
experimental: {
appDir: true,
serverActions: true,
},
webpack: (config) => {
if (config.name === 'server') config.optimization.concatenateModules = false

return config
},
}

module.exports = nextConfig
23 changes: 23 additions & 0 deletions examples/react/nextjs-suspense-streaming/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "@tanstack/query-example-nextjs-suspense-streaming",
"private": true,
"license": "MIT",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"@tanstack/react-query": "^v5.0.0-alpha.68",
"@tanstack/react-query-devtools": "^v5.0.0-alpha.68",
"next": "^13.4.4",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"superjson": "^1.12.3"
},
"devDependencies": {
"@types/node": "20.2.5",
"@types/react": "18.2.8",
"typescript": "5.1.3"
}
}
10 changes: 10 additions & 0 deletions examples/react/nextjs-suspense-streaming/src/app/api/wait/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { NextResponse } from 'next/server'

export async function GET(request: Request) {
const { searchParams } = new URL(request.url)
const wait = Number(searchParams.get('wait'))

await new Promise((resolve) => setTimeout(resolve, wait))

return NextResponse.json(`waited ${wait}ms`)
}
20 changes: 20 additions & 0 deletions examples/react/nextjs-suspense-streaming/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Providers } from './providers'

export const metadata = {
title: 'Next.js',
description: 'Generated by Next.js',
}

export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body>
<Providers>{children}</Providers>
</body>
</html>
)
}
89 changes: 89 additions & 0 deletions examples/react/nextjs-suspense-streaming/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
'use client'
import { useQuery } from '@tanstack/react-query'
import { Suspense } from 'react'

// export const runtime = "edge"; // 'nodejs' (default) | 'edge'

function getBaseURL() {
if (typeof window !== 'undefined') {
return ''
}
if (process.env.VERCEL_URL) {
return `https://${process.env.VERCEL_URL}`
}
return 'http://localhost:3000'
}
const baseUrl = getBaseURL()
function useWaitQuery(props: { wait: number }) {
const query = useQuery({
queryKey: ['wait', props.wait],
queryFn: async () => {
const path = `/api/wait?wait=${props.wait}`
const url = baseUrl + path

console.log('fetching', url)
const res: string = await (
await fetch(url, {
cache: 'no-store',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this no-store-directive even if it's a client component?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont think it does anything on the client

})
).json()
return res
},
suspense: true,
})

return [query.data as string, query] as const
}

function MyComponent(props: { wait: number }) {
const [data] = useWaitQuery(props)

return <div>result: {data}</div>
}

export default function MyPage() {
return (
<>
<Suspense fallback={<div>waiting 100....</div>}>
<MyComponent wait={100} />
</Suspense>
<Suspense fallback={<div>waiting 200....</div>}>
<MyComponent wait={200} />
</Suspense>
<Suspense fallback={<div>waiting 300....</div>}>
<MyComponent wait={300} />
</Suspense>
<Suspense fallback={<div>waiting 400....</div>}>
<MyComponent wait={400} />
</Suspense>
<Suspense fallback={<div>waiting 500....</div>}>
<MyComponent wait={500} />
</Suspense>
<Suspense fallback={<div>waiting 600....</div>}>
<MyComponent wait={600} />
</Suspense>
<Suspense fallback={<div>waiting 700....</div>}>
<MyComponent wait={700} />
</Suspense>

<fieldset>
<legend>
combined <code>Suspense</code>-container
</legend>
<Suspense
fallback={
<>
<div>waiting 800....</div>
<div>waiting 900....</div>
<div>waiting 1000....</div>
</>
}
>
<MyComponent wait={800} />
<MyComponent wait={900} />
<MyComponent wait={1000} />
</Suspense>
</fieldset>
</>
)
}
29 changes: 29 additions & 0 deletions examples/react/nextjs-suspense-streaming/src/app/providers.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// app/providers.jsx
'use client'

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactQueryDevtools } from '@tanstack/react-query-devtools'
import React from 'react'
import { ReactQueryStreamedHydration } from '@tanstack/react-query-next-experimental'

export function Providers(props: { children: React.ReactNode }) {
const [queryClient] = React.useState(
() =>
new QueryClient({
defaultOptions: {
queries: {
staleTime: 5 * 1000,
},
},
}),
)

return (
<QueryClientProvider client={queryClient}>
<ReactQueryStreamedHydration>
{props.children}
</ReactQueryStreamedHydration>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
)
}
25 changes: 25 additions & 0 deletions examples/react/nextjs-suspense-streaming/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
]
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
2 changes: 1 addition & 1 deletion packages/react-query-devtools/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineConfig } from 'vitest/config'

export default defineConfig({
test: {
name: 'react-query-persist-client',
name: 'react-query-devtools',
dir: './src',
watch: false,
setupFiles: ['test-setup.ts'],
Expand Down
16 changes: 16 additions & 0 deletions packages/react-query-next-experimental/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// @ts-check

/** @type {import('eslint').Linter.Config} */
const config = {
extends: ['plugin:react/recommended', 'plugin:react-hooks/recommended'],
parserOptions: {
tsconfigRootDir: __dirname,
project: './tsconfig.eslint.json',
},
rules: {
'react/jsx-key': ['error', { checkFragmentShorthand: true }],
'react-hooks/exhaustive-deps': 'error',
},
}

module.exports = config
57 changes: 57 additions & 0 deletions packages/react-query-next-experimental/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"name": "@tanstack/react-query-next-experimental",
"version": "5.0.0-alpha.67",
"description": "Hydration utils for React Query in the NextJs app directory",
"author": "tannerlinsley",
"license": "MIT",
"repository": "tanstack/query",
"homepage": "https://tanstack.com/query",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"type": "module",
"types": "build/lib/index.d.ts",
"main": "build/lib/index.legacy.cjs",
"module": "build/lib/index.legacy.js",
"exports": {
".": {
"types": "./build/lib/index.d.ts",
"import": "./build/lib/index.js",
"require": "./build/lib/index.cjs",
"default": "./build/lib/index.cjs"
},
"./package.json": "./package.json"
},
"sideEffects": false,
"files": [
"build/lib/*",
"src"
],
"scripts": {
"clean": "rimraf ./build && rimraf ./coverage",
"test:eslint": "eslint --ext .ts,.tsx ./src",
"test:types": "tsc --noEmit",
"test:lib": "vitest run --coverage --passWithNoTests",
"test:lib:dev": "pnpm run test:lib --watch",
"test:build": "publint --strict",
"build": "pnpm build:rollup && pnpm build:types",
"build:rollup": "rollup --config rollup.config.js",
"build:types": "tsc --emitDeclarationOnly"
},
"devDependencies": {
"@tanstack/react-query": "workspace:*",
"@types/react": "^18.2.4",
"@types/react-dom": "^18.2.4",
"next": "^13.4.6",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^3.1.4"
},
"peerDependencies": {
"@tanstack/react-query": "workspace:*",
"next": "^13.0.0",
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
12 changes: 12 additions & 0 deletions packages/react-query-next-experimental/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// @ts-check

import { defineConfig } from 'rollup'
import { buildConfigs } from '../../scripts/getRollupConfig.js'

export default defineConfig(
buildConfigs({
name: 'react-query-next-experimental',
outputFile: 'index',
entryFile: './src/index.ts',
}),
)
Loading