Schemas and Normalized data
Schemas are a declarative definition of how to process responses
- where to expect Entities
- Classes to deserialize fields
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.
- State
- Response
- Endpoint
- Entity
- React

[
  { "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
- Create
- Update
- Delete
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.