Complex Loader Management Hook for React.
Read the Medium post "Managing Complex Waiting Experiences on Web UIs".
react-wait is a React Hook helps to manage multiple loading states on the page without any conflict. It's based on a very simple idea that manages an Array of multiple loading states. The built-in loader component listens its registered loader and immediately become loading state.
React has its own Suspense feature to manage all the async works. For now it only supports code-splitting (not data-fetching).
useWait allows you to manage waiting experiences much more explicitly and not only for Promised/async patterns but also complete loading management.
Here's a quick overview that what's useWait for:
import{useWait,Waiter}from"react-wait";functionA(){const{ isWaiting }=useWait();return(<div>{isWaiting("creating user") ? "Creating User..." : "Nothing happens"}</div>);}functionB(){const{ anyWaiting }=useWait();return(<div>{anyWaiting() ? "Something happening on app..." : "Nothing happens"}</div>);}functionC(){const{ startWaiting, endWaiting, isWaiting }=useWait();functioncreateUser(){startWaiting("creating user");// Faking the async work:setTimeout(()=>{endWaiting("creating user");},1000);}return(<buttondisabled={isWaiting("creating user")}onClick={createUser}><Waiton="creating user"fallback={<Spinner/>}>
Create User
</Wait></button>);}ReactDOM.render(<Waiter><C/></Waiter>,document.getElementById("root"));If you are a try and learn developer, you can start trying the react-wait now using codesandbox.io.
yarn add react-waitimport{Waiter,useWait}from"react-wait";functionUserCreateButton(){const{ startWaiting, endWaiting, isWaiting, Wait }=useWait();return(<buttononClick={()=>startWaiting("creating user")}disabled={isWaiting("creating user")}><Waiton="creating user"fallback={<div>Creating user!</div>}>
Create User
</Wait></button>);}And you should wrap your App with Waiter component. It's actually a Context.Provider that provides a loading context to the component tree.
constrootElement=document.getElementById("root");ReactDOM.render(<Waiter><App/></Waiter>,rootElement);$ yarn add react-wait
# or if you using npm
$ npm install react-waitreact-wait provides some helpers to you to use in your templates.
Returns boolean value if any loader exists in context.
const{ anyWaiting }=useWait();return<buttondisabled={anyWaiting()}>Disabled while waiting</button>;Returns boolean value if given loader exists in context.
const{ isWaiting }=useWait();return(<buttondisabled={isWaiting("creating user")}>
Disabled while creating user
</button>);Starts the given waiter.
const{ startWaiting }=useWait();return<buttononClick={()=>startWaiting("message")}>Start</button>;Stops the given waiter.
const{ end }=useWait();return<buttononClick={()=>endWaiting("message")}>Stop</button>;functionComponent(){const{ Wait }=useWait();return(<Waiton="the waiting message"fallback={<div>Waiting...</div>}>
The content after waiting done
</Wait>);}Better example for a button with loading state:
<buttondisabled={isWaiting("creating user")}><Waiton="creating user"fallback={<div>Creating User...</div>}>
Create User
</Wait></button>With reusable loader components, you will be able to use custom loader components as example below. This will allow you to create better user loading experience.
functionSpinner(){return<imgsrc="spinner.gif"/>;}Now you can use your spinner everywhere using waiting attribute:
<buttondisabled={isWaiting("creating user")}><Waiton="creating user"fallback={<Spinner/>}>
Create User
</Wait></button>To keep your code DRY you can create a Waiting Context using createWaitingContext.
functionCreateUserButton(){const{ createWaitingContext }=useWait();// All methods will be curried with "creating user" on.const{ startWaiting, endWaiting, isWaiting, Wait }=createWaitingContext("creating user");functioncreateUser(){startWaiting();setTimeout(endWaiting,1000);}return(<Buttondisabled={isWaiting()}onClick={createUser}><Waitfallback="Creating User...">Create User</Wait></Button>);}- Fatih Kadir Akın, (creator)
Since react-wait based on a very simple idea, it can be implemented on other frameworks.
- vue-wait: Multiple Process Loader Management for Vue.
- dom-wait: Multiple Process Loader Management for vanilla JavaScript.
MIT © Fatih Kadir Akın

