Learn about our RFC process, Open RFC meetings & more.Join in the discussion! »

@data-provider/core

2.6.0 • Public • Published

Build status Coverage Status Quality Gate Mutation testing badge

NPM dependencies Renovate Last commit Last release

NPM downloads License

Data Provider

Async Data Provider. Powered by Redux. Agnostic about data origins. Framework agnostic.

Data Provider is a data provider (surprise!) with states ands built-in cache for JavaScript apps.

The main target of the library are front-end applications, but it could be used also in Node.js.

It helps you providing async data to your components informing them about loading and error states. It also provides a cache layer, so you don´t have to worry about when to read the data, and allows you to combine the results of different data providers using a syntax very similar to the known Reselect, recalculating them only when one of the dependencies cache is cleaned.

As its states are managed with Redux, you can take advantage of his large ecosystem of addons, which will improve the developer experience. (You don't need to use Redux directly in your application if you don't want, the library includes its own internal store for that purpose, which can be migrated to your own store).

You can use Data Provider with React, or with any other view library. Separated addons are available for that purpose, as @data-provider/react.

Data Provider is agnostic about data origins, so it can be used to read data from a REST API, from localStorage, or from any other origin. Choose one of the available plugins depending of the type of the origin you want to read from, as @data-provider/axios, or @data-provider/browser-storage.

It has a light weight, 4.2KB gzipped in UMD format (you have to add the Redux weight to this), and addons usually are even lighter.

Docs

We have a website available to help you to learn to use Data Provider. There are tutorials, examples and many other resources to guide you to understand from the basic concepts to the more advanced patterns:

Main features

Agnostic about data origins

The Provider class provides the cache, state handler, etc., but not the "read" method. The "read" behavior is implemented by different Data Provider Origins addons.

There are different origins available, such as Axios, LocalStorage, Memory, etc. and building your own is so easy as extending the Provider class with a custom "readMethod".

Sharing the same interface for all origins, and being able to build Selectors combining all of them implies that your logic will be completely isolated about WHERE the data is being retrieved.

import { Axios } from "@data-provider/axios";
import { LocalStorage } from "@data-provider/browser-storage";
 
export const books = new Axios("books", {
  url: "/api/books"
});
 
export const favoriteBooks = new LocalStorage("favorite-books", {
  initialState: {
    data: []
  }
});

Selectors inspired by Reselect

Selectors cache is cleaned whenever any dependency cache is cleaned.

Exposing the same interface than providers make consumers agnostic about what type of Provider or Selector are they consuming.

As in Reselect, Selectors are composable. They can be used as input to other selectors.

Powerful dependencies api: Catch dependencies errors, retrieve them in parallel, declare them as functions returning other providers or selectors, etc.

import { Selector } from "@data-provider/core";
 
import { booksProvider } from "data/books";
import { authorsProvider } from "data/authors";
 
export const booksWithAuthor = new Selector(
  booksProvider,
  authorsProvider,
  (books, authors) => {
    return books.map(book => ({
      ...book,
      author: authors.find(
        author => author.id === book.authorId
      )
    }))
  }
);

Cache and memoization

The built-in cache ensures that Providers are computed only once.

Don't care about when a data has to be retrieved. Simply retrieve it always, Data Provider will do the optimization. Avoid orchestrators and build fully modular pieces.

Cache can be cleaned on-demand, and some specific origins providers implementations even do it automatically when needed.

import Books from "views/books";
 
const RenderBooksTwice = () => {
  return (
    <div>
      <Books />
      <Books />
    </div>
  );
};
 
export default RenderBooksTwice;

Queryable

Providers and selectors instances can be queried, which returns a new child instance with his own "query value".

Each different child has a different cache, different state, etc.

Different origins can use the "query" value for different purposes (API origins will normally use it for adding different params or query strings to the provider url)

When the parent provider cache is clean, also the children is. (For example, cleaning the cache of an API origin requesting to "/api/books", will also clean the cache for "/api/books?author=2")

import { useData, useLoading } from "@data-provider/react";
 
import { bookProvider } from "data/books";
import BookCard from "components/book-card";
 
const Book = ({ id }) => {
  const provider = bookProvider.query({ id });
  const book = useData(provider);
  const loading = useLoading(provider);
 
  if (loading) {
    return <Loading />;
  }
  return <BookCard title={book.title} author={book.author} />;
};
 
export default Book;

UI binding addons

Data Provider is not concerned about the views, but UI binding addons are available.

For example, the @data-provider/react package gives you HOCs to connect providers to your components, creating a wrapper component handling all the logic for you.

It also provides hooks like "useData", "useLoading", etc.

Optimized, it takes care of reading the data and re-renders the component only when your desired props have changed.

import { withDataProvider } from "@data-provider/react";
 
import { booksProvider } from "data/books";
import ErrorComponent from "components/error";
 
const Books = ({ data, loading, error }) => {
  if (error) {
    return <ErrorComponent error={error}/>
  }
  return <BooksList data={data} loading={loading} />;
};
 
export default withDataProvider(booksProvider)(Books);

Contributing

Contributors are welcome. Please read the contributing guidelines and code of conduct.

Install

npm i @data-provider/core

DownloadsWeekly Downloads

595

Version

2.6.0

License

Apache-2.0

Unpacked Size

112 kB

Total Files

8

Last publish

Collaborators

  • avatar