Skip to main content
Version: 6.5

Upgrading from 4 to 5

Deprecation Removals

These previously deprecated members have been removed:

Resource.getKey() -> Resource.key

Simply rename this to get key()

Resource.getEntitySchema() -> Resource

This has been simplified to simply use the Resource itself:

class MyResource extends Resource {
static customEndpoint<T extends typeof MyResource>(this: T) {
return {
...super.listShape(),
// notice the next line
schema: { results: [this.getEntitySchema()], nextPage: '' },
};
}
}

Other breaking changes

yarn add @rest-hooks/test@2 @rest-hooks/legacy@2

Be sure to also upgrade these libraries if you use them:

  • @rest-hooks/test@2
  • @rest-hooks/legacy@2

These libraries don't have any breaking changes within themselves, but they do require rest-hooks@5 and (reflexively) rest-hooks@5 requires at least v2.

Network Definitions (Resource/FetchShape, etc)

FetchShape: {type: 'delete'} -> { type: 'mutate', schema: new schemas.Delete(this) }

Resource.deleteShape() will continue to work as expected. However, if you defined some custom shapes with type: 'delete'

class MyResource extends Resource {
static someOtherDeleteShape<T extends typeof Resource>(
this: T,
): DeleteShape<any, Readonly<object>> {
const options = this.getFetchOptions();
return {
// changed
type: 'delete',
// changed
schema: this.asSchema(),
options,
getFetchKey: (params: object) => {
return 'DELETE ' + this.url(params);
},
fetch: (params: Readonly<object>) => {
return this.fetch('delete', this.url(params));
},
};
}
}
Validation Errors: `This is likely due to a malformed response`

To aid with common schema definition or networking errors, Rest Hooks will sometimes throw an error. This only occurs during development, to help users correctly define their schemas and endpoints.

While the heuristics have been heavily tuned, if you don't believe the errors reported are valid please report a bug.

When reporting, be sure to include

Alternatively, this can be disabled by adding static automaticValidation = 'silent' | 'warn'

class MyResource extends Resource {
static automaticValidation = 'silent' as const;
// ...
}

Warn will no longer throw an error, but still add a message to the browser console. Silent removes the check completely.

Imports

import { reducer, NetworkManager } from '@rest-hooks/core'

Many 'advanced' features of rest-hooks are not longer exported by 'rest-hooks' package itself, but require importing from @rest-hooks/core

  • reducer
  • NetworkManager
  • action creators:
    • createFetch
    • createReceive
    • createReceiveError

Managers

These only apply if you have a custom Manager

action.meta.url -> action.meta.key

It's recommend to now use the action creators exported from @rest-hooks/core

  • createFetch
  • createReceive
  • createReceiveError
getState()

This is very unlikely to make a difference, but the internal cache state (accessible with getState()) might be slightly different. Mutations now result in entries in meta and results. This brings them more in line with reads, making the distinction simply about which hooks they are allowed in. (To prevent unwanted side effects.)

Cache Lifetime Policy

useInvalidator() triggers suspense

You can likely remove invalidIfStale if used in conjunction with useInvalidator()

invalidIfStale is still useful to disable the stale-while-revalidate policy.

`delete` suspends instead of throwing 404

Delete marks an entity as deleted. Any response requiring that entity will suspend. Previously it throw a 404 error.

Missing entities suspend

Required entities missing from network response will now throw error in useSuspense() just like other unexpected deserializations.

Use SimpleRecord for optional entities.

const schema = {
data: MyEntity,
};
invalidIfStale

When invalidIfStale is true, useCache() and useStatefulResource() will no longer return entities, even if they are in the cache. This matches the expected behavior that any loading data should not be usable.

Upgrading from beta versions to final

The last breaking changes introduced to rest-hook were in delta.0 where TTL and deletes were reworked. If you are on a more recent beta (i, j, k, rc), upgrades should be as simple as updating the version.

If this is not the case, please report a bug.

Deprecations

After a successful upgrade, it is recommended to adopt the modern practices.

Resource.fetchOptionsPlugin() -> Resource.getFetchInit()
class AuthdResource extends Resource {
static fetchOptionsPlugin = (options: RequestInit) => ({
...options,
credentials: 'same-origin',
});
}

(Resource.getFetchInit())/rest/api/resource#static-getfetchinitinit-requestinit-requestinit)

Resource.getFetchOptions() -> Resource.getEndpointExtra()
class PollingResource extends Resource {
static getFetchOptions(): FetchOptions {
return {
pollFrequency: 5000, // every 5 seconds
};
}
}

(Resource.getEndpointExtra())/rest/api/resource#static-getendpointextra--endpointextraoptions--undefined)

Resource.asSchema() -> Resource

This has been simplified to simply use the Resource itself:

class MyResource extends Resource {
static customEndpoint<T extends typeof MyResource>(this: T) {
return {
...super.listShape(),
// notice the next line
schema: { results: [this.asSchema()], nextPage: '' },
};
}
}

@rest-hooks/legacy

For v5 of Rest Hooks, the existing Resource and SimpleResource classes will be exported.

In v6, this will no longer be the case. However, they will continue to live in @rest-hooks/legacy, allowing easy safe upgrade to v6 by simply changing the import path. However, it is still recommended to try to migrate to @rest-hooks/rest as this is the future. v1 of @rest-hooks/rest will be the easiest to start with.

yarn add @rest-hooks/legacy
import { Resource } from 'rest-hooks';

class MyResource extends Resource {}

@rest-hooks/rest

Rest Hooks is protocol agnostic, so the REST/CRUD specific class Resource will eventually be fully deprecated and removed. @rest-hooks/rest is intended as its replacement. Other supplementary libraries like @rest-hooks/graphql could be added in the future, for intance. This is also beneficial as these libraries change more frequently than the core of rest hooks.

yarn add @rest-hooks/rest
import { Resource } from 'rest-hooks';

class MyResource extends Resource {}

Breaking change:

Nested entities static schema will return from useSuspense()

static schema

Nesting entities inside a schema will now denormalize those nested items.

import { Resource } from 'rest-hooks';

class ArticleResource extends Resource {
// other stuff omitted
readonly user: string = '';

static schema = {
user: UserResource,
};
}
FetchShape -> Endpoint

Endpoints use the builder pattern to make customization easy. Use extend() to customize.

@rest-hooks/endpoint is also its own package. This empowers you to publish interfaces for public APIs by marking @rest-hooks/endpoint as a peerDependency in the package.

import { Resource } from 'rest-hooks';

export default class UserResource extends Resource {
/** Retrieves current logged in user */
static currentShape<T extends typeof Resource>(this: T) {
return {
...this.detailShape(),
getFetchKey: () => {
return '/current_user/';
},
fetch: (params: {}, body?: Readonly<object | string>) => {
return this.fetch('post', `/current_user/`, body);
},
};
}
}

Currently all Endpoints also implement the FetchShape interface, so feel free to incrementally migrate. This means using Endpoint and extended via object spreads will still work:

import { Resource } from 'rest-hooks';

export default class UserResource extends Resource {
static currentShape<T extends typeof Resource>(this: T) {
return {
// this is an Endpoint, but can be spread the same way
...this.detail(),
getFetchKey: () => {
return '/current_user/';
},
fetch: (params: {}, body?: Readonly<object | string>) => {
return this.fetch('post', `/current_user/`, body);
},
};
}
}

Eventually support for FetchShape will be deprecated, and then removed.

Summary of interface differences

  • schema is optional
  • type removed in favor of sideEffect
    • type = 'read' -> sideEffect = undefined
    • type = 'mutate' -> sideEffect = true
  • options members elevated to top
  • top level object should be the actual fetch

Full Release notes