@ngspot/remote-data
v1.2.1
Published
[![MIT](https://img.shields.io/packagist/l/doctrine/orm.svg?style=flat-square)]() [![commitizen](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square)]() [![PRs](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=
Downloads
59
Maintainers
Readme
RemoteData
A library for tracking status of Remote Data with loading and error information.
Features
- ✅ Simple syntax that reduces boilerplate
- ✅ Configurable for many scenarios
- ✅ Compatible with any framework
Additional functionality
- for easy integration of RemoteData tracking with RxJS streams
Installation
NPM
npm install @ngspot/remote-data
Yarn
yarn add @ngspot/remote-data
The RemoteData data structure
At the core of the pattern is an object that lets developers track the current state of the data. The data could be in one of the four mutually exclusive states:
- Not asked
- Loading
- Success
- Error
These states are represented by the following object:
interface RemoteData<T, E> {
state: 'notAsked' | 'loading' | 'success' | 'error';
isLoading: boolean;
value?: T;
error?: E;
}
The RemoteData data structure is flexible enough to accommodate two scenarios:
- when the UI displays completely separate components during the different states
- when the UI does not remove the previously loaded data during the loading state
The RemoteData builders
This library provides builder functions that let the developer easily set one of the desired states of the data:
// [optionally] set the data state to "not asked"
let data = notAskedState();
function userClickHandler() {
// set the data state tp "loading"
data = loadingState();
api.loadDataPromise()
.then((response) => {
// set the data state tp "success"
data = successState(response);
})
.catch(error) => {
// set the data state tp "error"
data = errorState(error);
}
}
Rendering data using RemoteData
The RemoteData
structure is convenient to use when rendering items in the template.
Here's one example of usage:
Angular
<!-- Show a spinner if state is loading -->
<my-loading-spinner *ngIf="data.state === 'loading'"></my-loading-spinner>
<!-- Show the data if state is loaded -->
<my-data-view
*ngIf="data.state === 'success'"
[data]="data.value"
></my-data-view>
<!-- Show an error message if state is error -->
<my-error-view
*ngIf="data.state === 'error'"
[error]="data.error"
></my-error-view>
React
return (
<>
// Show a spinner if state is loading
{data.state === 'loading' && <my-loading-spinner></my-loading-spinner>}
// Show the data if state is loaded
{data.state === 'success' && (
<my-data-view data={data.value}></my-data-view>
)}
// Show an error message if state is error
{data.state === 'error' && (
<my-error-view error={data.error}></my-error-view>
)}
</>
);
RemoteData guards
For convenience, the library provides type guard functions to the asset current state:
function isNotAskedState(data: RemoteData): data is NotAskedState;
function isLoadingState<T>(data: RemoteData<T>): data is LoadingState<T>;
function isSuccessState<T>(data: RemoteData<T>): data is SuccessState<T>;
function isErrorState<T, E>(data: RemoteData<T, E>): data is ErrorState<T, E>;
Previous Art
The library is heavily inspired by:
- Kris Jenkins' blog post about How Elm slays a UI antipattern
- https://github.com/joanllenas/ngx-remotedata
- https://github.com/daiscog/ngx-http-request-state
License
MIT © Dmitry Efimenko