Skip to main content

6 posts tagged with "resource"

View All Tags

· 6 min read
Nathaniel Tucker

Collections enable Arrays and Objects to be easily extended by pushing or unshifting new members. The namesake comes from Backbone Collections.

Collections were first introduced in @rest-hooks/[email protected]. @rest-hooks/rest@7 takes this one step further, but using them in Resource.getList.

Fixtures
GET /users
async response(...args){return(await UserResource.getList(...args)).slice(0,3);}
GET /todos
async response(...args){return(await TodoResource.getList(...args)).slice(0,7);}
PATCH /todos/:id
async response(...args){return{...(await TodoResource.partialUpdate(...args)),id:args?.[0]?.id};}
POST /todos
async response(...args){//await new Promise(resolve => setTimeout(resolve, 500));
return{...(await TodoResource.getList.push(...args)),id:randomId()};}
TodoResource
import { Entity } from '@rest-hooks/rest';
import { createResource } from '@rest-hooks/rest/next';
export class Todo extends Entity {
id = 0;
userId = 0;
title = '';
completed = false;
pk() {
return `${this.id}`;
}
static key = 'Todo';
}
export const TodoResource = createResource({
urlPrefix: 'https://jsonplaceholder.typicode.com',
path: '/todos/:id',
searchParams: {} as { userId?: string | number } | undefined,
schema: Todo,
optimistic: true,
});
TodoItem
import { useController } from '@rest-hooks/react/next';
import { TodoResource, type Todo } from './TodoResource';
export default function TodoItem({ todo }: { todo: Todo }) {
const ctrl = useController();
const handleChange = e =>
ctrl.fetch(
TodoResource.partialUpdate,
{ id: todo.id },
{ completed: e.currentTarget.checked },
);
const handleDelete = () =>
ctrl.fetch(TodoResource.delete, {
id: todo.id,
});
return (
<div className="listItem nogap">
<label>
<input
type="checkbox"
checked={todo.completed}
onChange={handleChange}
/>
{todo.completed ? <strike>{todo.title}</strike> : todo.title}
</label>
<CancelButton onClick={handleDelete} />
</div>
);
}
CreateTodo
import { useController } from '@rest-hooks/react/next';
import { TodoResource } from './TodoResource';
export default function CreateTodo({ userId }: { userId: number }) {
const ctrl = useController();
const handleKeyDown = async e => {
if (e.key === 'Enter') {
ctrl.fetch(TodoResource.getList.push, {
userId,
title: e.currentTarget.value,
id: Math.random(),
});
e.currentTarget.value = '';
}
};
return (
<div className="listItem nogap">
<label>
<input type="checkbox" name="new" checked={false} disabled />
<input type="text" onKeyDown={handleKeyDown} />
</label>
</div>
);
}
TodoList
import { useSuspense } from '@rest-hooks/react/next';
import { TodoResource } from './TodoResource';
import TodoItem from './TodoItem';
import CreateTodo from './CreateTodo';
function TodoList() {
const userId = 1;
const todos = useSuspense(TodoResource.getList, { userId });
return (
<div>
{todos.map(todo => (
<TodoItem key={todo.pk()} todo={todo} />
))}
<CreateTodo userId={userId} />
</div>
);
}
render(<TodoList />);
Live Preview
Loading...
Store

Upgrading is quite simple, as @rest-hooks/rest/next and @rest-hooks/react/next were introduced to allow incremental adoption of the new APIs changed in this release. This makes the actual upgrade a simple import rename.

Other highlights include

Upgrade to Rest Hooks 8 guide

· 5 min read
Nathaniel Tucker

Rest Hooks 7

For most people, upgrading to Rest Hooks 7 is as easy as upgrading the packages as long as you aren’t using previously (2 years ago) deprecated exports.

npm install --save rest-hooks@7 @rest-hooks/react@6 @rest-hooks/redux@6 @rest-hooks/test@9 @rest-hooks/[email protected]

The big difference here is all react-specific code has been moved into @rest-hooks/react, which is now a peer dependency of the other packages. The rest-hooks package re-exports everything from @rest-hooks/react.

Upgrade to Rest Hooks 7 guide

@rest-hooks/react@7

Once the rest-hooks package is upgraded, you can optionally upgrade @rest-hooks/react to 7.

npm install --save @rest-hooks/react@7

React Native

Because the React Native and Web interfaces are the same, we ship them in the same package and delivery appropriate specializations where appropriate.

The only breaking change is that useSuspense, useSubscription, useLive, useFetch are all react-native aware. This is unlikely to cause any issue, as screen focus will trigger fetches on stale data.

@rest-hooks/react@7.1

New additions in 7.1

@rest-hooks/ssr@0.7

Newly added guide and utilities specific for making NextJS integration easier.

· 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

· 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' });

· 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]);
}
}