React Nested Loader
The easiest way to manage loaders/errors inside a button. NOT an UI lib.
- Manage loading/error state of nested views/buttons triggering async actions
- Not an UI lib, you provide the UI. Works with ReactNative.
- No boilerplate at all, no need to use setState/Redux
Main usecase: button triggering api calls
You have a submit button on your form. For good UX you may want to:
- show temporarily a spinner into the button
- disable the button during the async operation
- make the button blink on api errors
Unfortunately, you are using Redux/setState/whatever, and implementing this kind of UX detail takes too much time/pollutes state/creates boilerplate so it is left for later while it doesn't have to.
Usage
npm install react-nested-loader
1) Create a button:
The button UI should be able to display appropriately loading/error states. You define the styling entirely.
2) Wrap your button:
The ReactNestedLoader
HOC will by default inject a loading=false
and error=undefined
prop to the wrapped component.
3) Return a promise in container/smartComp/controller:
Using the LoadingButton
into a top-level component.
No need to use any local state, you just need to return the promise to the button, and the loading
/ error
prop of your button will be automatically updated according to the state of the last intercepted promise.
API
Or
Options
Features
- Works with React and React-Native
- The callback proxies are cached appropriately so that the underlying button does not render unnecessarily. If you provide stable callbacks, the HOC will pass-down stable proxies and your pure component button can bypass rendering
- Will only handle the loading state of the last returned promise, to avoid concurrency issues (think
takeLatest
of Redux-saga`) - API injected as prop into button (
props.reactNestedLoader.handlePromise(promise))
- Can use React.forwardRef() (2.*)
- Imperative API, when not forwarding ref (
componentRef.api.handlePromise(promise)
)
Limits
The HOC does hold the button loading state as React component state. This means it won't be in your state management system (Redux/Apollo/Mobx...) and as any local state you will loose ability to use devtools to replay that state (or other fancy features). In my opinion it is not critical state that is worth putting in your Redux store anyway. I assume perfectly using this lib as well as Redux/Redux-saga/Apollo mutations.
Currently the lib only support injecting a single loading
prop. As a component may receive multiple callbacks, we could inject multiple loading props. Please open issues with your specific usecase if needed.
Advices
- Wrap generic app button with
ReactNestedLoader
and manage theloading
prop inside it to show some alternative content like a spinner - When button component change from
loading=false
toloading=true
, make sure the component dimension is not affected for better UX - A nice UX is to make the text disappear and make the spinner appear, as it does not mess-up with button dimensions (make sure to use a small-enough spinner)
- If needed, pass spinner size in button props
TODOS
- Find more explicit name?
- Support more advanced usecases?
- Tests