Loading
The loading plugin for Rematch. Adds automated loading indicators for effects, so you don't need to manage state like loading: true
by yourself. Inspired by dva-loading.
Compatibility​
Install the correct version of loading plugin based on the version of the core Rematch library in your project.
@rematch/core | @rematch/loading |
---|---|
1.x.x | 1.x.x |
2.x.x | 2.x.x |
Install​
- npm
- Yarn
bash
npm install @rematch/loading
bash
npm install @rematch/loading
bash
yarn add @rematch/loading
bash
yarn add @rematch/loading
loadingPlugin([config])​
The loading plugin accepts one optional argument - config, which is an object with the following properties:
- [
name
] (string?): key for the loading model in your store. If you name it "custom", loading state can be accessed from state.custom. Defaults to loading. - [
asNumber
] (boolean?): loading plugin by default keeps track of running effects using booleans, so for example: state.loading.global === true. You can change that behaviour and use numbers instead - plugin will keep track of the number of times an effect was executed, for example: state.loading.global === 5. Defaults to false. Deprecated, usetype
instead - [
type
] ("number"|"boolean"|"full"): Loading plugin by default keeps track of running effects using booleans, but sometimes you want to track if the effect promise is resolved to an Error, or loading, or if the promise is resolved correctly, in that case you can usefull
. If you want to track the number of times an effect was executed, you can usenumber
instead. - [
whitelist
] (string[]?): an array of effects names that you want to use loading plugin for. If defined, plugin will work only for the whitelisted effects. - [
blacklist
] (string[]?): an array of effects names that you don't want to use loading plugin for. If defined, plugin will work for all effects except those blacklisted.
Both blacklist
and whitelist
accept the "full" effect name, in a format modelName/effectFunctionName
, for example 'count/addOne'.
If both blacklist
and whitelist
aren't provided, plugin works for all effects.
Usage​
Let's say we have a model 'count' in our store. Loading plugin's state will have the following format:
json
{"global": true, // true when any effect in any model is loading"models": {"count": true // true when any effect in 'count' model is loading},"effects": {"count": {"addOne": true // true when effect 'addOne' in model 'count' is loading}}}
json
{"global": true, // true when any effect in any model is loading"models": {"count": true // true when any effect in 'count' model is loading},"effects": {"count": {"addOne": true // true when effect 'addOne' in model 'count' is loading}}}
Check out below an example of how to use loading plugin in React:
Set up your store with default or custom settings.
Setup the store​
store.tsts
// @filename: store.tsimportloadingPlugin , {ExtraModelsFromLoading } from "@rematch/loading"import {init ,RematchDispatch ,RematchRootState } from "@rematch/core"import {models ,RootModel } from "./models"ÂtypeFullModel =ExtraModelsFromLoading <RootModel >Âexport conststore =init <RootModel ,FullModel >({models ,plugins : [loadingPlugin ()],})Âexport typeStore = typeofstore export typeDispatch =RematchDispatch <RootModel >export typeRootState =RematchRootState <RootModel ,FullModel >
store.tsts
// @filename: store.tsimportloadingPlugin , {ExtraModelsFromLoading } from "@rematch/loading"import {init ,RematchDispatch ,RematchRootState } from "@rematch/core"import {models ,RootModel } from "./models"ÂtypeFullModel =ExtraModelsFromLoading <RootModel >Âexport conststore =init <RootModel ,FullModel >({models ,plugins : [loadingPlugin ()],})Âexport typeStore = typeofstore export typeDispatch =RematchDispatch <RootModel >export typeRootState =RematchRootState <RootModel ,FullModel >
If you want to use the loadingPlugin
with numbers instead of booleans, you can also change the typings:
ts
// @filename: storeAsNumber.tsimportloadingPlugin , {ExtraModelsFromLoading } from "@rematch/loading"import {init ,RematchDispatch ,RematchRootState } from "@rematch/core"import {models ,RootModel } from "./models"ÂtypeFullModel =ExtraModelsFromLoading <RootModel , {type : 'number' }>Âexport conststore =init <RootModel ,FullModel >({models ,plugins : [loadingPlugin ({type : 'number' })],})Âexport typeStore = typeofstore export typeDispatch =RematchDispatch <RootModel >export typeRootState =RematchRootState <RootModel ,FullModel >
ts
// @filename: storeAsNumber.tsimportloadingPlugin , {ExtraModelsFromLoading } from "@rematch/loading"import {init ,RematchDispatch ,RematchRootState } from "@rematch/core"import {models ,RootModel } from "./models"ÂtypeFullModel =ExtraModelsFromLoading <RootModel , {type : 'number' }>Âexport conststore =init <RootModel ,FullModel >({models ,plugins : [loadingPlugin ({type : 'number' })],})Âexport typeStore = typeofstore export typeDispatch =RematchDispatch <RootModel >export typeRootState =RematchRootState <RootModel ,FullModel >
If you want to use the loadingPlugin
with detailed Errors and Success information instead of booleans, you can also change the typings:
ts
// @filename: storeAsFull.tsimportloadingPlugin , {ExtraModelsFromLoading } from "@rematch/loading"import {init ,RematchDispatch ,RematchRootState } from "@rematch/core"import {models ,RootModel } from "./models"ÂtypeFullModel =ExtraModelsFromLoading <RootModel , {type : 'full' }>Âexport conststore =init <RootModel ,FullModel >({models ,plugins : [loadingPlugin ({type : 'full' })],})Âexport typeStore = typeofstore export typeDispatch =RematchDispatch <RootModel >export typeRootState =RematchRootState <RootModel ,FullModel >
ts
// @filename: storeAsFull.tsimportloadingPlugin , {ExtraModelsFromLoading } from "@rematch/loading"import {init ,RematchDispatch ,RematchRootState } from "@rematch/core"import {models ,RootModel } from "./models"ÂtypeFullModel =ExtraModelsFromLoading <RootModel , {type : 'full' }>Âexport conststore =init <RootModel ,FullModel >({models ,plugins : [loadingPlugin ({type : 'full' })],})Âexport typeStore = typeofstore export typeDispatch =RematchDispatch <RootModel >export typeRootState =RematchRootState <RootModel ,FullModel >
React usage​
Use state created by the loading plugin in your view.
Default​
tsx
// @filename: appTemplate.tsximportReact from 'react'import {useSelector } from 'react-redux'import {RootState } from './store'Âexport constApp = () => {constisCountLoading =useSelector ((rootState :RootState ) =>rootState .loading .models .count )if (isCountLoading ) return <div >LOADING...</div >Âreturn <div >Data succesfully loaded</div >}
tsx
// @filename: appTemplate.tsximportReact from 'react'import {useSelector } from 'react-redux'import {RootState } from './store'Âexport constApp = () => {constisCountLoading =useSelector ((rootState :RootState ) =>rootState .loading .models .count )if (isCountLoading ) return <div >LOADING...</div >Âreturn <div >Data succesfully loaded</div >}
Full​
tsx
// @filename: appTemplate.tsximportReact from 'react'import {useSelector } from 'react-redux'import {RootState } from './storeAsFull'Âexport constApp = () => {const {loading ,success ,error } =useSelector ((rootState :RootState ) =>rootState .loading .models .count )if (loading ) return <div >LOADING...</div >if (error ) return <div >{(error asError ).name }</div >Âreturn <div >Data succesfully loaded</div >}
tsx
// @filename: appTemplate.tsximportReact from 'react'import {useSelector } from 'react-redux'import {RootState } from './storeAsFull'Âexport constApp = () => {const {loading ,success ,error } =useSelector ((rootState :RootState ) =>rootState .loading .models .count )if (loading ) return <div >LOADING...</div >if (error ) return <div >{(error asError ).name }</div >Âreturn <div >Data succesfully loaded</div >}
Number​
tsx
// @filename: appTemplate.tsximportReact from 'react'import {useSelector } from 'react-redux'import {RootState } from './storeAsNumber'Âexport constApp = () => {constcountCalledTimes =useSelector ((rootState :RootState ) =>rootState .loading .models .count )if (countCalledTimes > 0) return <div >LOADING...</div >Âreturn <div >Data succesfully loaded</div >}
tsx
// @filename: appTemplate.tsximportReact from 'react'import {useSelector } from 'react-redux'import {RootState } from './storeAsNumber'Âexport constApp = () => {constcountCalledTimes =useSelector ((rootState :RootState ) =>rootState .loading .models .count )if (countCalledTimes > 0) return <div >LOADING...</div >Âreturn <div >Data succesfully loaded</div >}