Skip to main content
Version: 4.5

Schemas and Normalized data

Schemas are a declarative definition of how to process responses

import { Endpoint, Entity } from '@rest-hooks/endpoint';

class Todo extends Entity {
readonly id: number = 0;
readonly userId: number = 0;
readonly title: string = '';
readonly completed: boolean = false;

pk() {
return `${this.id}`;
}
}

const TodoDetail = new Endpoint(
({ id })fetch(`https://jsonplaceholder.typicode.com/todos/${id}`),
{ schema: Todo }
);

Entities

Entities have a primary key. This enables easy access via a lookup table. This makes it easy to find, update, create, or delete the same data - no matter what endpoint it was used in.

Entities cache

[
{ "id": 1, "title": "this is an entity" },
{ "id": 2, "title": "this is the second entity" }
]
const PresentationList = new Endpoint(
() => fetch(`/presentations`).then(res => res.json()),
{ schema: [PresentationEntity] },
);
class PresentationEntity extends Entity {
readonly id: string = '';
readonly title: string = '';

pk() {
return this.id;
}
}
export function PresentationsPage() {
const presentation = useResource(PresentationList, {});
return presentation.map(presentation => (
<div key={presentation.pk()}>{presentation.title}</div>
));
}

Mutations and Dynamic Data

import { schema, Endpoint } from '@rest-hooks/endpoint';

const todoCreate = new Endpoint(
(body: FormData) =>
fetch(`https://jsonplaceholder.typicode.com/todos/`, {
method: 'POST',
body,
}).then(res => res.json()),
{ schema: Todo, sideEffect: true },
);
Example Usage
import { useFetcher } from 'rest-hooks';

export default function NewTodoForm() {
const create = useFetcher(todoCreate);
return (
<Form onSubmit={e => create(new FormData(e.target))}>
<FormField name="title" />
</Form>
);
}
import { schema, Endpoint } from '@rest-hooks/endpoint';

const todoUpdate = new Endpoint(
({ id }: { id: number }, body: FormData) =>
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`, {
method: 'PUT',
body,
}).then(res => res.json()),
{ schema: Todo, sideEffect: true },
);
Example Usage
import { useFetcher } from 'rest-hooks';

export default function UpdateTodoForm({ id }: { id: number }) {
const todo = useResource(todoDetail, { id });
const update = useFetcher(todoUpdate);
return (
<Form
onSubmit={e => update({ id }, new FormData(e.target))}
initialValues={todo}
>
<FormField name="title" />
</Form>
);
}
import { schema, Endpoint } from '@rest-hooks/endpoint';

const todoDelete = new Endpoint(
({ id }: { id: number }) =>
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`, {
method: 'DELETE',
}).then(() => ({ id })),
{ schema: new schema.Delete(Todo), sideEffect: true },
);
Example Usage
import { useFetcher } from 'rest-hooks';
import ArticleResource from 'resources/article';

export default function TodoWithDelete({ todo }: { todo: Todo }) {
const del = useFetcher(todoDelete);
return (
<div>
{todo.title}
<button onClick={() => del({ id: todo.id })}>Delete</button>
</div>
);
}

Mutations automatically update the normalized cache, resulting in consistent and fresh data.