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(),
schema: { results: [this.getEntitySchema()], nextPage: '' },
};
}
}
class MyResource extends Resource {
static customEndpoint<T extends typeof MyResource>(this: T) {
return {
...super.listShape(),
schema: { results: [this], nextPage: '' },
};
}
}
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.
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 {
type: 'delete',
schema: this.asSchema(),
options,
getFetchKey: (params: object) => {
return 'DELETE ' + this.url(params);
},
fetch: (params: Readonly<object>) => {
return this.fetch('delete', this.url(params));
},
};
}
}
import { schemas } from 'rest-hooks';
class MyResource extends Resource {
static someOtherDeleteShape<T extends typeof Resource>(
this: T,
): DeleteShape<any, Readonly<object>> {
const options = this.getFetchInit();
return {
type: 'mutate',
schema: new schemas.Delete(this),
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.
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
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.)
useInvalidator() triggers suspense
`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,
};
class OptionalSchema extends SimpleRecord {
readonly data: MyEntity | null = null;
static schema = {
data: MyEntity,
};
}
const schema = OptionalSchema;
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.
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.
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',
});
}
class AuthdResource extends Resource {
static getFetchInit = (init: RequestInit) => ({
...init,
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,
};
}
}
class PollingResource extends Resource {
static getEndpointExtra(): FetchOptions {
return {
pollFrequency: 5000,
};
}
}
(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(),
schema: { results: [this.asSchema()], nextPage: '' },
};
}
}
class MyResource extends Resource {
static customEndpoint<T extends typeof MyResource>(this: T) {
return {
...super.listShape(),
schema: { results: [this], nextPage: '' },
};
}
}
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 {}
import { Resource } from '@rest-hooks/legacy';
class MyResource extends Resource {}
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 {}
import { Resource } from '@rest-hooks/rest';
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 {
readonly user: string = '';
static schema = {
user: UserResource,
};
}
const article = useSuspense(ArticleResource.detail(), { id });
const user = useCache(UserResource.detail(), { id: article.user });
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 {
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);
},
};
}
}
import { Resource } from '@rest-hooks/rest';
export default class UserResource extends Resource {
static current<T extends typeof Resource>(this: T) {
const endpoint = this.detail();
return endpoint.extend({
fetch() { return endpoint(this); }
url() { return '/current_user/' },
})
}
}
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.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.
- 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
If you have any trouble upgrading, you can get some help from the community discord 
If you find any bugs or other issues, feel free to open a github ticket