Skip to content
This repository has been archived by the owner on Nov 28, 2023. It is now read-only.

Commit

Permalink
Add a Nextra docs site (#20)
Browse files Browse the repository at this point in the history
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
Schniz and kodiakhq[bot] authored Aug 30, 2022
1 parent 9a006b2 commit 081761c
Show file tree
Hide file tree
Showing 10 changed files with 1,911 additions and 30 deletions.
5 changes: 5 additions & 0 deletions packages/docs/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
6 changes: 6 additions & 0 deletions packages/docs/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const withNextra = require("nextra")({
theme: "nextra-theme-docs",
themeConfig: "./theme.config.tsx",
});

module.exports = withNextra();
27 changes: 27 additions & 0 deletions packages/docs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "docs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"next": "^12.2.4",
"nextra": "beta",
"nextra-theme-docs": "beta",
"react": "^18.1.0",
"react-dom": "^18.1.0"
},
"devDependencies": {
"@types/node": "^17.0.38",
"@types/react": "^18.0.10",
"@types/react-dom": "^18.0.5",
"typescript": "^4.7.2"
}
}
128 changes: 128 additions & 0 deletions packages/docs/pages/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Next Fetch

Think in React, instead about routing: Next Fetch is an intuitive way to dynamically fetch data from API endpoints in Next.js, using your favorite libraries.

💃 Import your API endpoints instead of making a stringified dance

🔒 Infer the types end-to-end for your data based on its implementation

⚛ Think in React, instead of routing: you only export a React hook!

🕵 Embrace best-practices: input validation, error handling, etc.

🌐 Use `Request` and `Response` classes as building blocks, no matter what runtime you're running on (Node.js or Edge)

📝 Use `<Form />` component for making progressive enhanced experiences

🤯 Supports [SWR](https://swr.vercel.app) and [React Query](https://tanstack.com/query/v4) out of the box!

## What does that mean?

Next Fetch is using compile-time transformations to allow you to _import_ your API endpoints instead of referecing them as plain strings, while keeping the type definitions co-located with the implementation.

<table>
<thead>
<tr>
<th></th>
<th>Next.js + Next Fetch</th>
<th>Plain Next.js</th>
</tr>
</thead>

<tbody>
<tr>
<td>API implementation</td>
<td>

```tsx
// pages/api/message.swr.tsx
import { query } from "@next-fetch/swr";
import z from "zod";

export const useMessage = query(
// use zod for input validation
z.object({
name: z.string(),
}),
async function ({ name }) {
// this.request is a `Request` instance
return { hello: `world, ${name}` };
}
);
```

</td>
<td>

```tsx
// pages/api/message.tsx
import type { NextApiRequest, NextApiResponse } from "next";

export default (req: NextApiRequest, res: NextApiResponse) => {
// ad-hoc input validation
const name = Array.isArray(req.query.name)
? req.query.name[0]
: req.query.name;
if (!name) {
return res.status(400).json({ error: "No name provided" });
}

// explicit type defniitions required
return res.status(200).json({ hello: `world, ${name}` });
};
```

</td>
</tr>
<tr>
<td>API consumption</td>
<td>

```tsx
import { useMessage } from "./api/message";

export default function MyPage() {
const { data, error } = useMessage({
// will autocomplete and
// type-check the input arguments
name: "John Doe",
});

// autocompletes and type-checks!
const hello = data?.hello;

return <div>{/* ... */}</div>;
}
```

</td>
<td>

```tsx
// pages/index.tsx
import useSWR from "swr";

const fetcher = (url: string) => {
const response = await fetch(url);

// handle input validation or runtime errors
if (!response.ok) {
const text = await response.text().catch(() => null);
throw new Error(`response is not okay${text ? `: ${text}` : ""}`);
}

return await response.json();
};

export default function MyPage() {
const { data, error } = useSWR("/api/message?name=John%20Doe", fetcher);
/** `data` is `any`, so we need to explicitly type-cast here */
return <div>{/* ... */}</div>;
}
```

</td>
</tr>
</tbody>

</table>
5 changes: 5 additions & 0 deletions packages/docs/pages/meta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"index": "Introduction",
"swr": "Using SWR",
"react-query": "Using React Query"
}
129 changes: 129 additions & 0 deletions packages/docs/pages/react-query.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
title: "Next Fetch + React Query quickstart"
---

import { Callout } from "nextra-theme-docs";

<Callout type="info">
Looking for integrating Next Fetch with SWR? [Check out the SWR integration
guide](./swr).
</Callout>

Next Fetch supports [React Query v4](https://tanstack.com/query/v4) out of the box, through the `@next-fetch/react-query` package.

## Set up React Query

First, make sure you went through [React Query's quick start guide](https://tanstack.com/query/v4/docs/quick-start) to set up the necessary environment. The `QueryClientProvider` needs to be set up in `_app` to allow React Query to work properly.

## Installation

Assuming you already installed React Query v4 in your project, install `@next-fetch/react-query` and your runtime type validation of choice. In this guide we will use [Zod](https://zod.dev).

```bash
# pnpm
pnpm add @next-fetch/react-query zod
# yarn
yarn add @next-fetch/react-query zod
# npm
npm install --save @next-fetch/react-query zod
```

## Set up `next.config.js`

Within your `next.config.js` file, make the following changes to use `withReactQueryApiEndpoints`:

```diff
+ const { withReactQueryApiEndpoints } = require("@next-fetch/react-query");
+
const config = { /* ... */ };
- module.exports = config;
+ module.exports = withReactQueryApiEndpoints(config);
```

Now you can restart your app, to make sure the changes in `next.config.js` are applied.

## Create your first API endpoint

Any `pages/api/*.rq.ts` file will be automatically compiled using Next Fetch's compiler. For our test, we can create a simple `pages/api/simple.rq.ts` endpoint:

```ts
// pages/api/simple.rq.ts

import { query } from "@next-fetch/react-query";
import z from "zod";

export const useMessage = query(
z.object({ name: z.string() }),
async ({ name }) => {
return { message: `Hello ${name}` };
}
);
```

## Use the API endpoint in any page

```ts
// pages/index.tsx

import { useMessage } from "./api/simple.rq";

export default function Home() {
const { data, error, isLoading } = useMessage({ name: "World" });

if (isLoading) {
return <div>Loading...</div>;
}

if (error) {
return <div>Error: {String(error)}</div>;
}

return <div>{data.message}</div>;
}
```

## Add a mutation to your API endpoint

```ts
// pages/api/simple.rq.ts

export const useMutation = query(
z.object({ name: z.string() }),
async ({ name }) => {
return { message: "Hello " + name };
},
{
// This will be called when the form is sent before JavaScript loads
// and enables to add logic for smart server-side redirections
hookResponse(data) {
const newUrl = new URL("/form", this.request.url);
newUrl.searchParams.set("message", data.message);
return Response.redirect(newUrl.toString(), 302);
},
}
);
```

## Use the `<Form />` component to call the mutation

```ts
// pages/form.tsx

import { useMutation } from "./api/simple.rq";
import { Form } from "@next-fetch/react-query/form";

export default function MyFormPage() {
const mutation = useMutation();

return (
<Form mutation={mutation}>
<input type="text" name="name" />
<button type="submit">Submit</button>
</Form>
);
}
```

## That's it.

Now you have a fullly working app with Next Fetch and React Query.
Loading

2 comments on commit 081761c

@vercel
Copy link

@vercel vercel bot commented on 081761c Aug 30, 2022

Choose a reason for hiding this comment

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

@vercel
Copy link

@vercel vercel bot commented on 081761c Aug 30, 2022

Choose a reason for hiding this comment

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

Successfully deployed to the following URLs:

next-fetch – ./packages/docs

next-fetch-pi.vercel.app
next-fetch-vercel-labs.vercel.app
next-fetch-git-main-vercel-labs.vercel.app

Please sign in to comment.