Voltar ao ranking

reactive/data-client

TypeScriptdataclient.io

Async State Management without the Management. REST, GraphQL, SSE, Websockets

reactsuspensetypescriptnormalizednormalizrfetchreact-nativereactive-programmingsse-clientstate-managementexpohooks
Crescimento de estrelas
Estrelas
2k
Forks
99
Crescimento semanal
Issues
3
1k2k
fev. de 2019jul. de 2021jan. de 2024jul. de 2026
Artefatosnpmnpm install data-client
README
Reactive Data Client

The scalable way to build applications with dynamic data.

Declarative resouce definitons for REST, GraphQL, Websockets+SSE and more
Performant rendering in React, NextJS, React Native, Expo, Vue

Schema driven. Zero updater functions.

CircleCI Coverage Status Percentage of issues still open bundle size npm version PRs Welcome Agent Skills Chat

📖Read The Docs  |  🏁Getting Started  |  🤖Agent Skills
🎮 Demos:   Todo  |  Github Social  |  NextJS SSR  |  Websockets+SSR

Installation

npm install --save @data-client/react @data-client/rest @data-client/test

For more details, see the Getting Started docs page.

Skills

npx skills add reactive/data-client

Then run skill "data-client-setup"

Usage

Simple TypeScript definition

class User extends Entity {
  id = '';
  username = '';
}

class Article extends Entity {
  id = '';
  title = '';
  body = '';
  author = User.fromJS();
  createdAt = Temporal.Instant.fromEpochMilliseconds(0);

  static schema = {
    author: User,
    createdAt: Temporal.Instant.from,
  };
}

Create collection of API Endpoints

const UserResource = resource({
  path: '/users/:id',
  schema: User,
  optimistic: true,
});

const ArticleResource = resource({
  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 (
  <>
    <CreateArticleForm
      onSubmit={article =>
        ctrl.fetch(ArticleResource.getList.push, { id }, article)
      }
    />
    <ProfileForm
      onSubmit={user =>
        ctrl.fetch(UserResource.update, { id: article.author.id }, user)
      }
    />
    <button onClick={() => ctrl.fetch(ArticleResource.delete, { id })}>
      Delete
    </button>
  </>
);

Subscriptions

const price = useLive(PriceResource.get, { symbol });
return price.value;

Type-safe Imperative Actions

const ctrl = useController();
await ctrl.fetch(ArticleResource.update, { id }, articleData);
await ctrl.fetchIfStale(ArticleResource.get, { id });
ctrl.expireAll(ArticleResource.getList);
ctrl.invalidate(ArticleResource.get, { id });
ctrl.invalidateAll(ArticleResource.getList);
ctrl.setResponse(ArticleResource.get, { id }, articleData);
ctrl.set(Article, { id }, articleData);

Programmatic queries

const queryTotalVotes = new Query(
  new Collection([BlogPost]),
  posts => posts.reduce((total, post) => total + post.votes, 0),
);

const totalVotes = useQuery(queryTotalVotes);
const totalVotesForUser = useQuery(queryTotalVotes, { userId });
const groupTodoByUser = new Query(
  TodoResource.getList.schema,
  todos => Object.groupBy(todos, todo => todo.userId),
);
const todosByUser = useQuery(groupTodoByUser);

Powerful Middlewares

class LoggingManager implements Manager {
  middleware: Middleware = controller => next => async action => {
    console.log('before', action, controller.getState());
    await next(action);
    console.log('after', action, controller.getState());
  };

  cleanup() {}
}
class TickerStream implements Manager {
  middleware: Middleware = controller => {
    this.handleMsg = msg => {
      controller.set(Ticker, { id: msg.id }, msg);
    };
    return next => action => next(action);
  };

  init() {
    this.websocket = new WebSocket('wss://ws-feed.myexchange.com');
    this.websocket.onmessage = event => {
      const msg = JSON.parse(event.data);
      this.handleMsg(msg);
    };
  }
  cleanup() {
    this.websocket.close();
  }
}

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

Examples

  • Todo: GitHub | Sandbox | Edit on CodeSandbox
  • Github: GitHub | Sandbox
  • NextJS: GitHub | Sandbox | Edit on CodeSandbox
  • Websockets: GitHub | Sandbox | Website

API

Reactive Applications

Define Data

Networking definition

Data model
Data Type Mutable Schema Description Queryable
Object Entity, EntityMixin single unique object
Union(Entity) polymorphic objects (A | B)
🛑 Object statically known keys 🛑
Invalidate(Entity) delete an entity 🛑
List Collection(Array) growable lists
🛑 Array immutable lists 🛑
All list of all entities of a kind
Map Collection(Values) growable maps
🛑 Values immutable maps 🛑
Scalar Scalar lens-dependent entity fields
any Query(Queryable) memoized custom transforms
Lazy(Schema) deferred denormalization
Repositórios relacionados
freeCodeCamp/freeCodeCamp

freeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.

TypeScriptnpmBSD 3-Clause "New" or "Revised" Licenselearn-to-codenonprofits
contribute.freecodecamp.org
452.4k45.6k
react/react

The library for web and native user interfaces.

JavaScriptnpmMIT Licensejavascriptreact
react.dev
246.7k51.3k
facebook/react

The library for web and native user interfaces.

JavaScriptnpmMIT Licensejavascriptreact
react.dev
233k47.8k
vercel/next.js

The React Framework

JavaScriptnpmMIT Licensereactserver-rendering
nextjs.org
141.1k31.5k
react/react-native

A framework for building native applications using React

C++MIT Licenseandroidapp-framework
reactnative.dev
126.2k25.2k
facebook/react-native

A framework for building native applications using React

C++MIT Licenseandroidapp-framework
reactnative.dev
120.9k24.5k
shadcn-ui/ui

A set of beautifully-designed, accessible components and a code distribution platform. Works with your favorite frameworks. Open Source. Open Code.

TypeScriptnpmMIT Licensecomponentsnextjs
ui.shadcn.com
119.5k9.5k
justjavac/free-programming-books-zh_CN

:books: 免费的计算机编程类中文书籍,欢迎投稿

GNU General Public License v3.0pythonjavascript
weibo.com/justjavac
117.7k28.2k
nextlevelbuilder/ui-ux-pro-max-skill

An AI SKILL that provide design intelligence for building professional UI/UX multiple platforms

PythonPyPIMIT Licenseai-skillsantigravity
uupm.cc
108.6k11.6k
react/create-react-app

Set up a modern web app by running one command.

JavaScriptnpmMIT Licensereactzero-configuration
create-react-app.dev
103.3k26.9k
facebook/create-react-app

Set up a modern web app by running one command.

JavaScriptnpmMIT Licensereactzero-configuration
create-react-app.dev
103.1k27k
ant-design/ant-design

An enterprise-class UI design language and React UI library

TypeScriptnpmMIT Licensereactui-kit
ant.design
98.8k54.7k