Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
134 changes: 115 additions & 19 deletions src/routes/solid-router/reference/response-helpers/json.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,134 @@ tags:
- json
- api
- actions
- cache
- queries
- revalidation
- response
version: '1.0'
version: "1.0"
description: >-
Return JSON data from actions with cache revalidation control. Configure how
Return JSON data from actions with query revalidation control. Configure how
route data updates after mutations for optimal performance.
---

Returns JSON data from an action while also providing options for controlling revalidation of cache data on the route.
The `json` function returns a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object that contains the provided data.
It is intended for sending JSON data from a [query](/solid-router/reference/data-apis/query) or [action](/solid-router/concepts/actions) while also allowing configuration of query revalidation.

```ts title="/actions/get-completed-todos.ts" {7}
import { action, json } from "@solidjs/router";
import { fetchTodo } from "../fetchers";
This works both in client and server (e.g., using a server function) environments.

const getCompletedTodos = action(async () => {
const completedTodos = await fetchTodo({ status: 'complete' });
## Import

return json(completedTodos, { revalidate: getTodo.keyFor(id) });
});
```ts
import { json } from "@solidjs/router";
```

Also read [action](/solid-router/reference/data-apis/action) and [revalidate](/solid-router/reference/response-helpers/revalidate).
## Type

## Type Signature
```ts
function json<T>(
data: T,
init: {
revalidate?: string | string[];
headers?: HeadersInit;
status?: number;
statusText?: string;
} = {}
): CustomResponse<T>;
```

## Parameters

### `data`

- **Type:** `T`
- **Required:** Yes

The data to be serialized as JSON in the response body.
It must be a value that can be serialized with [`JSON.stringify`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify).

### `init`

- **Type:** `{ revalidate?: string | string[]; headers?: HeadersInit; status?: number; statusText?: string; }`
- **Required:** No

An optional configuration object with the following properties:

#### `revalidate`

- **Type:** `string | string[]`
- **Required:** No

A query key or an array of query keys to revalidate.
Passing an empty array (`[]`) disables query revalidation entirely.

#### `headers`

- **Type:** `HeadersInit`
- **Required:** No

An object containing any headers to be sent with the response.

#### `status`

```typescript
interface ResponseOptions & Omit<ResponseInit, "body"> {
revalidate?: string | string[];
- **Type:** `number`
- **Required:** No

The HTTP status code of the response.
Defaults to [`200 OK`](http://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/200).

#### `statusText`

- **Type:** `string`
- **Required:** No

The status text associated with the status code.

## Examples

### Invalidating Data After a Mutation

```tsx
import { For } from "solid-js";
import { query, action, json, createAsync } from "@solidjs/router";

const getCurrentUserQuery = query(async () => {
return await fetch("/api/me").then((response) => response.json());
}, "currentUser");

const getPostsQuery = query(async () => {
return await fetch("/api/posts").then((response) => response.json());
}, "posts");

const createPostAction = action(async (formData: FormData) => {
const title = formData.get("title")?.toString();
const newPost = await fetch("/api/posts", {
method: "POST",
body: JSON.stringify({ title }),
}).then((response) => response.json());

// Only revalidate the "posts" query.
return json(newPost, { revalidate: "posts" });
}, "createPost");

function Posts() {
const currentUser = createAsync(() => getCurrentUserQuery());
const posts = createAsync(() => getPostsQuery());

return (
<div>
<p>Welcome back {currentUser()?.name}</p>
<ul>
<For each={posts()}>{(post) => <li>{post.title}</li>}</For>
</ul>
<form action={createPostAction} method="post">
<input name="title" />
<button>Create Post</button>
</form>
</div>
);
}
```

json<T>(data: T, opt?: ResponseOptions): CustomResponse<T>;
```
## Related

The `ResponseOptions` extens the types from the native [`ResponseInit`](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response#options) interface.
- [`query`](/solid-router/reference/data-apis/query)
- [`action`](/solid-router/reference/data-apis/action)
129 changes: 73 additions & 56 deletions src/routes/solid-router/reference/response-helpers/redirect.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,89 +10,106 @@ tags:
- routing
- authorization
- forms
version: '1.0'
version: "1.0"
description: >-
Redirect users between routes with proper status codes. Handle authentication
flows, form submissions, and protected route access.
---

Redirects to the next route.
When done over a server RPC (Remote Procedure Call), the redirect will be done through the server.
By default the status code of a `redirect()` is `302 - FOUND`, also known as a temporary redirect.
The `redirect` function returns a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object that instructs the router to navigate to a different route when returned or thrown from a [query](/solid-router/reference/data-apis/query) or [action](/solid-router/concepts/actions).

Other useful redirect codes:
This works both in client and server (e.g., using a server function) environments.

| Code | Description |
| ---- | ----------- |
| `301` | Moved Permanently |
| `307` | Temporary Redirect |
| `308` | Permanent redirect |
## Import

:::tip[Redirect Methods]
307 and 308 won't allow the browser to change the method of the request.
If you want to change the method, you should use 301 or 302.
:::
```ts
import { redirect } from "@solidjs/router";
```

A common use-case for throwing a redirect is when a user is not authenticated and needs to be sent to the login page or another public route.
## Type

```js title="/queries/get-user.ts" {7}
import { query, redirect } from "@solidjs/router";
import { getCurrentUser } from "../auth";

const getUser = query(() => {
const user = await getCurrentUser();

if (!user) throw redirect("/login");

return user;
}, "get-user")
```ts
function redirect(
url: string,
init?:
| number
| {
revalidate?: string | string[];
headers?: HeadersInit;
status?: number;
statusText?: string;
}
): CustomResponse<never>;
```

## Single-Flight Mutations
## Parameters

When using `redirect` during a Server Action, the redirect will be done through the server.
The response value will automatically send data for the destination route, avoiding a subsequent roundtrip to load the data from the target route.
### `url`

This is useful when redirecting the user to a different route once a mutation is done.
- **Type:** `string`
- **Required:** Yes

```ts title="/actions/add-user.ts" {3,6}
import { action, redirect } from "@solidjs/router";
The absolute or relative URL to which the redirect should occur.

const addUser = action(async (user: User) => {
await postUser(user);

return redirect("/users");
});
```
### `init`

The `addUser` action will redirect the user to the `/users` route once the user has been added to the database.
The response from the form action will send the updated data for the `/users` route without the developer needing to revalidate or reload.
- **Type:** `number | { revalidate?: string | string[]; headers?: HeadersInit; status?: number; statusText?: string; }`
- **Required:** No

## Throw vs Return
Either a number representing the status code or a configuration object with the following properties:

Both `throw` and `return` can be used to redirect the user to a different route.
For general usage `throw` is recommended as it immediately stops the execution of the current action and redirects the user.
#### `revalidate`

When returning from a nested method, the parent method will continue to execute, which can lead to unexpected behavior.
- **Type:** `string | string[]`
- **Required:** No

### TypeScript Signature
A query key or an array of query keys to revalidate on the destination route.

```typescript
type RouterResponseInit = Omit<ResponseInit, "body"> & {
revalidate?: string | string[];
};
#### `status`

function redirect(url: string, init?: number | RouterResponseInit): CustomResponse<never>;
```
- **Type:** `number`
- **Required:** No

The `RouterResponseInit` type extends the native [`ResponseInit`](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response#options) interface.
The HTTP status code for the redirect.
Defaults to [`302 Found`)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/302).

## Revalidate Query Keys
## Examples

You can pass query keys to the redirect helper to revalidate them.
### Basic Usage

```ts
redirect("/", { revalidate: ["getUser", getUser.keyFor(id)] });
import { query, redirect } from "@solidjs/router";

const getCurrentUserQuery = query(async () => {
const response = await fetch("/api/me");

if (response.status === 401) {
return redirect("/login");
}

return await response.json();
}, "currentUser");
```

This will only invalidate the query keys passed to the redirect helper instead of the entire next page.
### Configuring Query Revalidation

```ts
import { action, redirect } from "@solidjs/router";

const loginAction = action(async (formData: FormData) => {
const username = formData.get("username")?.toString();
const password = formData.get("password")?.toString();

await fetch("/api/login", {
method: "POST",
body: JSON.stringify({ username, password }),
}).then((response) => response.json());

return redirect("/users", { revalidate: ["currentUser"] });
}, "login");
```

## Related

- [`query`](/solid-router/reference/data-apis/query)
- [`action`](/solid-router/reference/data-apis/action)
Loading