Skip to main content

· 4 min read
Nathaniel Tucker

We recently release two new package versions Rest [email protected] and @rest-hooks/[email protected]. These include some solutions to long-standing user-requested functionality. Additionally, we'll give a preview of even more features soon to come.

Rest Hooks 6.5

@rest-hooks/rest 6.1

  • Query provides programmatic access to the Rest Hooks store.
  • schema.All() retrieves all entities in the store. Very useful with Query

· One min read
Nathaniel Tucker

Mermaid is a cool way of creating diagrams in markdown. It was recently integrated into Github Markdown and added to this site's framework as well.

A lot of concepts are much easy to convey using visualizations so we quickly started using this in the docs. To start off we have added control flow diagrams to help with hooking into the lifecycles of Rest Hooks for customizations as well as understanding how it operates.

RestEndpoint

· 6 min read
Nathaniel Tucker

Today we're releasing @rest-hooks/rest version 6. While this is a pretty radical departure from previous versions, there is no need to upgrade if previous versions are working as they will continue to work with the current 6.4 release of Rest Hooks as well as many future versions.

First, we have completely decoupled the networking lifecycle RestEndpoint from the data lifecycle Schema. Collections of Endpoints that operate on the same data can be consgtructed by calling createResource.

RestEndpoint

import { RestEndpoint } from '@rest-hooks/rest';
export const getTodo = new RestEndpoint({
urlPrefix: 'https://jsonplaceholder.typicode.com',
path: '/todos/:id',
});
import { useSuspense } from 'rest-hooks';
import { getTodo } from './api/getTodo';
function TodoDetail({ id }: { id: number }) {
const todo = useSuspense(getTodo, { id });
return <div>{todo.title}</div>;
}
render(<TodoDetail id={1} />);
Live Preview
Loading...
Store

The new RestEndpoint optimizes configuration based around HTTP networking. Urls are constructed based on simple named parameters, which are enforced with strict TypeScript automatically.

createResource

import { Entity, createResource } from '@rest-hooks/rest';
export class Todo extends Entity {
id = 0;
userId = 0;
title = '';
completed = false;
pk() {
return `${this.id}`;
}
}
export const TodoResource = createResource({
urlPrefix: 'https://jsonplaceholder.typicode.com',
path: '/todos/:id',
schema: Todo,
});
import { useSuspense } from 'rest-hooks';
import { TodoResource } from './api/Todo';
function TodoDetail({ id }: { id: number }) {
const todo = useSuspense(TodoResource.get, { id });
return <div>{todo.title}</div>;
}
render(<TodoDetail id={1} />);
Live Preview
Loading...
Store

createResource creates a simple collection of RestEndpoints. These can be easily overidden, removed as appropriate - or not used altogether. createResource is intended as a quick start point and as a guide to best practices for API interface ergonomics. It is expected to extend or replace createResource based on the common patterns for your own API.

const todo = useSuspense(TodoResource.get, { id: '5' });
const todos = useSuspense(TodoResource.getList);
controller.fetch(TodoResource.create, { content: 'ntucker' });
controller.fetch(TodoResource.update, { id: '5' }, { content: 'ntucker' });
controller.fetch(
TodoResource.partialUpdate,
{ id: '5' },
{ content: 'ntucker' },
);
controller.fetch(TodoResource.delete, { id: '5' });

· 2 min read
Nathaniel Tucker

validateRequired() will validate that required fields are present; simplifying some common validation use cases. validateRequired() is available in @rest-hooks/@5.1.0 or greater.

class CustomBaseEntity extends Entity {
static validate(processedEntity) {
return validateRequired(processedEntity, this.defaults) || super.validate(processedEntity);
}
}

· 9 min read
Nathaniel Tucker

@rest-hooks/experimental is a new package that allows us to quickly iterate on new designs by using them in production, which provides feedback in ways not possible at design and testing phase.

This package is not api stable; it does follow semver, so it will never reach 1.0. However, it is tested with the same rigor we expect with Rest Hooks as we use it in production. It is recommend to use this for providing feedback or playing with designs, unless you are willing to put in extra work to make migrations. Detailed migration guides will only be provided upon upstreaming to the mainline packages.

Today this package comes with two new features:

useController()

const { fetch, invalidate, resetEntireStore } = useController();
fetch(MyResource.detail(), { id });

Resource.list().paginated()

class NewsResource extends Resource {
static listPage<T extends typeof NewsResource>(this: T) {
return this.list().paginated(({ cursor, ...rest }) => [rest]);
}
}

· One min read
Nathaniel Tucker

A lot of exciting features have been developed recently, resulting in many feature releases. We've been hard a work integrating them into Coinbase's various products, so I skipped a few release announcements. The biggest focus has been performance features - highlighted by adding true optimistic updates.

· One min read
Nathaniel Tucker

4.1 comes with a more granular data definition hierarchy that will make it easier to write more API definitions. This marked by the introduction of a new member known as Entity. Entity only needs a pk() and get key(), as well as member declarations to integrate fully.

Entity

  • Useful for nested entities that don't have endpoints like LatestPrice.
  • Useful for non-REST style APIs like GraphQL.
  • Simplifies defining nested entities.

· 4 min read
Nathaniel Tucker

2.2 comes with the eagerly awaited programmable optimistic updates. This enables two very important use cases: optimistic update on create and infinite pagination.

The bigger part of this release is introducing two new hooks that enable an incremental migration path to 3.0 planned changes. useCacheNew() and useResourceNew() are added in this release, allowing incremental adoption of the new selection logic that will become the default in 3.0. More details below.

· 3 min read
Nathaniel Tucker

New Features

Reduced bundle size with custom networking library

Resource comes with a default fetch() implementation to make getting started easy. It uses superagent as the networking library due to its server-side support as well as nice interface via the builder pattern. However, this comes at the cost of 6kb gziped added to the bundle. For those who want to use another networking library this is quite a cost to pay for a library that itself is well under 10kb gzip.

To solve this problem there is a new exported called SimpleResource. This provides all the Resource behavior without the fetch() implementation. If you're customizing fetch() or want to customize fetch(), simply follow the instructions to use SimpleResource as your base class now. With tree-shaking this will leave superagent out of your bundle and save a cool 6kb gzip.

Enable customizing networking library reducing bundle size #113