@data-client/react
v0.11.4
Published
High performance mutable data rendering in React.
Downloads
4,731
Maintainers
Readme
Define your async methods. Use them synchronously in React. Instantly mutate the data and automatically update all usages.
For REST, GraphQL, Websockets+SSE and more
📖Read The Docs | 🏁Getting Started | 🎮Todo Demo | 🎮Github Demo | 🎮NextJS SSR Demo
Installation
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
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
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
const article = useSuspense(ArticleResource.get, { id });
return (
<article>
<h2>
{article.title} by {article.author.username}
</h2>
<p>{article.body}</p>
</article>
);
Reactive Mutations
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>
);
Subscriptions
const price = useLive(PriceResource.get, { symbol });
return price.value;
Type-safe Imperative Actions
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 });
Programmatic queries
const queryTotalVotes = new schema.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 = useQuery(queryTotalVotes);
const totalVotesForUser = useQuery(queryTotalVotes, { userId });
Powerful Middlewares
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() {}
}
Integrated data mocking
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] 💦 Partial Hydration Server Side Rendering
- [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] 🚯 Declarative cache lifetime policy
- [x] 🧅 Composable middlewares
- [x] 💽 Global data consistency guarantees
- [x] 🏇 Automatic race condition elimination
- [x] 👯 Global referential equality guarantees
Examples
API
- Rendering: useSuspense(), useLive(), useCache(), useDLE(), useQuery()
- Event handling: useController() returns Controller
- Components: <CacheProvider/>, <AsyncBoundary/>, <ErrorBoundary/>
- Middleware: LogoutManager, NetworkManager, SubscriptionManager, PollingSubscription, DevToolsManager