diff --git a/examples/with-react-query/.gitignore b/examples/with-react-query/.gitignore new file mode 100644 index 0000000000000..1437c53f70bc2 --- /dev/null +++ b/examples/with-react-query/.gitignore @@ -0,0 +1,34 @@ +# 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 +.env.development.local +.env.test.local +.env.production.local + +# vercel +.vercel diff --git a/examples/with-react-query/README.md b/examples/with-react-query/README.md new file mode 100644 index 0000000000000..cff3e71779156 --- /dev/null +++ b/examples/with-react-query/README.md @@ -0,0 +1,36 @@ +This example is taken from the official documentation [React Query](https://github.com/tannerlinsley/react-query/tree/master/examples/nextjs). + +This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `pages/index.js`. The page auto-updates as you edit the file. + +[API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. + +The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. diff --git a/examples/with-react-query/components/Header/index.js b/examples/with-react-query/components/Header/index.js new file mode 100644 index 0000000000000..fdcb1dad063fa --- /dev/null +++ b/examples/with-react-query/components/Header/index.js @@ -0,0 +1,33 @@ +import React from 'react' +import { useRouter } from 'next/router' +import Link from 'next/link' + +export const Header = () => { + const { pathname } = useRouter() + + return ( +
+ + Home + + + + Client-Only + + + +
+ ) +} diff --git a/examples/with-react-query/components/InfoBox/index.js b/examples/with-react-query/components/InfoBox/index.js new file mode 100644 index 0000000000000..b0ff42f7d3416 --- /dev/null +++ b/examples/with-react-query/components/InfoBox/index.js @@ -0,0 +1,19 @@ +import React from 'react' + +const InfoBox = ({ children }) => ( +
+ + {children} +
+) + +export { InfoBox } diff --git a/examples/with-react-query/components/Layout/index.js b/examples/with-react-query/components/Layout/index.js new file mode 100644 index 0000000000000..3ffea4e4ccb3c --- /dev/null +++ b/examples/with-react-query/components/Layout/index.js @@ -0,0 +1,49 @@ +import React from 'react' + +export const Layout = ({ children }) => { + return ( +
+ {children} + +
+ ) +} diff --git a/examples/with-react-query/components/PostList/index.js b/examples/with-react-query/components/PostList/index.js new file mode 100644 index 0000000000000..7c74cdf4f1d64 --- /dev/null +++ b/examples/with-react-query/components/PostList/index.js @@ -0,0 +1,70 @@ +import React, { useState } from 'react' +import { usePosts } from '../../hooks/usePosts' + +export const PostList = () => { + const [postCount, setPostCount] = useState(10) + const { data, isLoading, isFetching } = usePosts(postCount) + + if (isLoading) return
Loading
+ + return ( +
+ + {postCount <= 90 && ( + + )} + +
+ ) +} diff --git a/examples/with-react-query/components/index.js b/examples/with-react-query/components/index.js new file mode 100644 index 0000000000000..31a8a0c10fef1 --- /dev/null +++ b/examples/with-react-query/components/index.js @@ -0,0 +1,4 @@ +export * from './Layout' +export * from './Header' +export * from './InfoBox' +export * from './PostList' diff --git a/examples/with-react-query/hooks/index.js b/examples/with-react-query/hooks/index.js new file mode 100644 index 0000000000000..e30241c69ebe2 --- /dev/null +++ b/examples/with-react-query/hooks/index.js @@ -0,0 +1 @@ +export * from './usePosts' diff --git a/examples/with-react-query/hooks/usePosts/index.js b/examples/with-react-query/hooks/usePosts/index.js new file mode 100644 index 0000000000000..8ead3ffbf1f08 --- /dev/null +++ b/examples/with-react-query/hooks/usePosts/index.js @@ -0,0 +1,14 @@ +import ky from 'ky-universal' +import { useQuery } from 'react-query' + +const fetchPosts = async (limit = 10) => { + const parsed = await ky('https://jsonplaceholder.typicode.com/posts').json() + const result = parsed.filter(x => x.id <= limit) + return result +} + +const usePosts = limit => { + return useQuery(['posts', limit], () => fetchPosts(limit)) +} + +export { usePosts, fetchPosts } diff --git a/examples/with-react-query/next.config.js b/examples/with-react-query/next.config.js new file mode 100644 index 0000000000000..78377bdec08a1 --- /dev/null +++ b/examples/with-react-query/next.config.js @@ -0,0 +1,48 @@ +const Module = require('module') +const path = require('path') +const resolveFrom = require('resolve-from') + +const node_modules = path.resolve(__dirname, 'node_modules') + +const originalRequire = Module.prototype.require + +// The following ensures that there is always only a single (and same) +// copy of React in an app at any given moment. +Module.prototype.require = function (modulePath) { + // Only redirect resolutions to non-relative and non-absolute modules + if ( + ['/react/', '/react-dom/', '/react-query/'].some(d => { + try { + return require.resolve(modulePath).includes(d) + } catch (err) { + return false + } + }) + ) { + try { + modulePath = resolveFrom(node_modules, modulePath) + } catch (err) { + // + } + } + + return originalRequire.call(this, modulePath) +} + +module.exports = { + webpack: config => { + config.resolve = { + ...config.resolve, + alias: { + ...config.resolve.alias, + react$: resolveFrom(path.resolve('node_modules'), 'react'), + 'react-query$': resolveFrom( + path.resolve('node_modules'), + 'react-query' + ), + 'react-dom$': resolveFrom(path.resolve('node_modules'), 'react-dom'), + }, + } + return config + }, +} \ No newline at end of file diff --git a/examples/with-react-query/package.json b/examples/with-react-query/package.json new file mode 100644 index 0000000000000..9cc56a4e91fa3 --- /dev/null +++ b/examples/with-react-query/package.json @@ -0,0 +1,25 @@ +{ + "name": "with-react-query", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "ky": "^0.23.0", + "ky-universal": "^0.8.2", + "next": "latest", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-query": "^3.5.0", + "resolve-from": "^5.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "devDependencies": { + "eslint": "7", + "eslint-config-next": "12.0.3" + } + } + \ No newline at end of file diff --git a/examples/with-react-query/pages/_app.js b/examples/with-react-query/pages/_app.js new file mode 100644 index 0000000000000..6d589308117e5 --- /dev/null +++ b/examples/with-react-query/pages/_app.js @@ -0,0 +1,16 @@ +import React from 'react' +import { Hydrate, QueryClient, QueryClientProvider } from 'react-query' +import { ReactQueryDevtools } from 'react-query/devtools' + +export default function MyApp({ Component, pageProps }) { + const [queryClient] = React.useState(() => new QueryClient()) + + return ( + + + + + + + ) +} diff --git a/examples/with-react-query/pages/client-only.js b/examples/with-react-query/pages/client-only.js new file mode 100644 index 0000000000000..364735141817d --- /dev/null +++ b/examples/with-react-query/pages/client-only.js @@ -0,0 +1,14 @@ +import React from 'react' +import { Layout, Header, InfoBox, PostList } from '../components' + +const ClientOnly = () => { + return ( + +
+ ℹ️ This data is loaded on client and not prefetched + + + ) +} + +export default ClientOnly diff --git a/examples/with-react-query/pages/index.js b/examples/with-react-query/pages/index.js new file mode 100644 index 0000000000000..0879aa3981828 --- /dev/null +++ b/examples/with-react-query/pages/index.js @@ -0,0 +1,28 @@ +import React from 'react' +import { dehydrate, QueryClient } from 'react-query' +import { Layout, Header, InfoBox, PostList } from '../components' +import { fetchPosts } from '../hooks' + +const Home = () => { + return ( + +
+ ℹ️ This page shows how to use SSG with React-Query. + + + ) +} + +export async function getStaticProps() { + const queryClient = new QueryClient() + + await queryClient.prefetchQuery(['posts', 10], () => fetchPosts(10)) + + return { + props: { + dehydratedState: dehydrate(queryClient), + }, + } +} + +export default Home