Rest Hooks
Async State Management without the Management
README
Reactive Data Client
Installation
- ```bash
- npm install --save @data-client/react @data-client/rest @data-client/test @data-client/hooks
- ```
For more details, see the Installation docs page.
Usage
Simple TypeScript definition
- ```typescript
- class User extends Entity {
- id = '';
- username = '';
- pk() {
- return this.id;
- }
- }
- class Article extends Entity {
- id = '';
- title = '';
- body = '';
- author = User.fromJS();
- createdAt = Temporal.Instant.fromEpochSeconds(0);
- pk() {
- return this.id;
- }
- static schema = {
- author: User,
- createdAt: Temporal.Instant.from,
- };
- }
- ```
Create collection of API Endpoints
- ```typescript
- const UserResource = createResource({
- path: '/users/:id',
- schema: User,
- optimistic: true,
- });
- const ArticleResource = createResource({
- path: '/articles/:id',
- schema: Article,
- searchParams: {} as { author?: string },
- optimistic: true,
- paginationField: 'cursor',
- });
- ```
One line data binding
- ```tsx
- const article = useSuspense(ArticleResource.get, { id });
- return (
- <article>
- <h2>
- {article.title} by {article.author.username}
- </h2>
- <p>{article.body}</p>
- </article>
- );
- ```
- ```tsx
- const ctrl = useController();
- return (
- <CreateProfileForm
- onSubmit={data => ctrl.fetch(UserResource.getList.push, { id }, data)}
- />
- <ProfileForm
- onSubmit={data => ctrl.fetch(UserResource.update, { id }, data)}
- />
- <button onClick={() => ctrl.fetch(UserResource.delete, { id })}>Delete</button>
- );
- ```
- ```tsx
- const price = useLive(PriceResource.get, { symbol });
- return price.value;
- ```
- ```tsx
- const ctrl = useController();
- ctrl.expireAll(ArticleResource.getList);
- ctrl.invalidate(ArticleResource.get, { id });
- ctrl.invalidateAll(ArticleResource.getList);
- ctrl.setResponse(ArticleResource.get, { id }, articleData);
- ctrl.fetch(ArticleResource.get, { id });
- ```
- ```tsx
- const queryTotalVotes = new Query(
- new schema.All(Post),
- (posts, { userId } = {}) => {
- if (userId !== undefined)
- posts = posts.filter(post => post.userId === userId);
- return posts.reduce((total, post) => total + post.votes, 0);
- },
- );
- const totalVotes = useCache(queryTotalVotes);
- const totalVotesForUser = useCache(queryTotalVotes, { userId });
- ```
- ```ts
- class LoggingManager implements Manager {
- getMiddleware = (): Middleware => controller => next => async action => {
- console.log('before', action, controller.getState());
- await next(action);
- console.log('after', action, controller.getState());
- };
- cleanup() {}
- }
- ```
- ```tsx
- const fixtures = [
- {
- endpoint: ArticleResource.getList,
- args: [{ maxResults: 10 }] as const,
- response: [
- {
- id: '5',
- title: 'first post',
- body: 'have a merry christmas',
- author: { id: '10', username: 'bob' },
- createdAt: new Date(0).toISOString(),
- },
- {
- id: '532',
- title: 'second post',
- body: 'never again',
- author: { id: '10', username: 'bob' },
- createdAt: new Date(0).toISOString(),
- },
- ],
- },
- {
- endpoint: ArticleResource.update,
- response: ({ id }, body) => ({
- ...body,
- id,
- }),
- },
- ];
- const Story = () => (
- <MockResolver fixtures={options[result]}>
- <ArticleList maxResults={10} />
- </MockResolver>
- );
- ```
...all typed ...fast ...and consistent
For the small price of 9kb gziped. 🏁Get started now
Features
- [x]
Strong Typescript inference
- [x] 🛌 React Suspense support
- [x] 🧵 React 18 Concurrent mode compatible
- [x] 🎣 Declarative API
- [x] 📝 Composition over configuration
- [x] 💰 Normalized caching
- [x] 💥 Tiny bundle footprint
- [x] 🛑 Automatic overfetching elimination
- [x] ✨ Optimistic updates
- [x] 🧘 Flexible to fit any API design (one size fits all)
- [x] 🔧 Debugging and inspection via browser extension
- [x] 🌳 Tree-shakable (only use what you need)
- [x] 🔁 Subscriptions
- [x] ♻️ Optional redux integration
- [x] 📙 Storybook mocking
- [x] 📱 React Native support
- [x] ⚛️ NextJS support
- [x] 🧅 Composable middlewares
- [x] 💽 Global data consistency guarantees
- [x] 🏇 Automatic race condition elimination
- [x] 👯 Global referential equality guarantees