https://github.com/yenshih/redux-awaiter
A Redux middleware for giving opportunities to await and receive actions in anywhere
https://github.com/yenshih/redux-awaiter
Last synced: 3 months ago
JSON representation
A Redux middleware for giving opportunities to await and receive actions in anywhere
- Host: GitHub
- URL: https://github.com/yenshih/redux-awaiter
- Owner: yenshih
- License: mit
- Created: 2017-10-05T06:58:05.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2018-01-02T05:51:14.000Z (over 7 years ago)
- Last Synced: 2025-02-20T02:11:17.161Z (4 months ago)
- Language: TypeScript
- Homepage:
- Size: 67.4 KB
- Stars: 2
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Redux Awaiter
Redux Awaiter is a Redux middleware for giving opportunities to await and receive actions in anywhere.It's tiny (gzip < 1kB, no dependencies).
[](https://travis-ci.org/yenshih/redux-awaiter)
[](https://coveralls.io/github/yenshih/redux-awaiter?branch=master)
[](https://www.npmjs.com/package/redux-awaiter)
[](https://www.npmjs.com/package/redux-awaiter)## Motivation
*[Local state is fine](https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367)*.
Redux Awaiter is designed to help us manage local state conveniently.
It's inspired by [Redux Saga](https://github.com/redux-saga/redux-saga/), but the problems they solve are totally different.
## Example
We can use Redux Awaiter and `async/await` to pause execution until an expected action has been dispatched.
```javascript
class UserListView extends React.PureComponent {
state = { loading: false };async componentDidMount() {
const { actions: { fetchUserList } } = this.props;
fetchUserList();
this.setState(state => ({ ...state, loading: true }));
// start loading, until RECEIVE_USER_LIST has been dispatched
await take('RECEIVE_USER_LIST');
// reducers may update `users` in redux store, stop loading
this.setState(state => ({ ...state, loading: false }));
}render() {
const { users } = this.props; // `users` is mapped from redux store
const { loading } = this.state;
return (
- {name} )}
{users.map(({ id, name }) =>
);
}
}
```
## Installation
```
npm i redux-awaiter
```
## Documentation
### Type Definition
Redux Awaiter is written in [TypeScript](http://www.typescriptlang.org/).
The internal type definition is based on [flux standard action](https://github.com/acdlite/flux-standard-action).
```typescript
type ActionType = string;
interface BaseAction {
type: ActionType;
}
interface Action
extends BaseAction {
payload: P;
meta?: M;
error?: true;
}
```
A pattern determines whether an action is matching.
```typescript
type Pattern
= string | RegExp | ((action: Action
) => boolean);
```
`object` pattern is not supported, use a function instead.
### API
#### createAwaiterMiddleware
```javascript
import { createStore, applyMiddleware } from 'redux';
import { createAwaiterMiddleware } from 'redux-awaiter';
const awaiterMiddleware = createAwaiterMiddleware();
const store = createStore(rootReducer, applyMiddleware(
// other middlewares (e.g. routerMiddleware)
awaiterMiddleware,
));
```
#### take
```typescript
const take:
(pattern: Pattern
) => Promise>;
```
`take` receives a pattern as its single argument, and returns a Promise which contains the first matching action.
```javascript
const action = await take('RECEIVE_DATA'); // action.type should be RECEIVE_DATA
```
#### takeAllOf
```typescript
const takeAllOf:
(patterns: Pattern
[]) => Promise[]>;
```
`takeAllOf` receives an array of patterns as its single argument, and returns a Promise which contains an array of actions corresponding to patterns.
Internally, `takeAllOf(patterns)` is the same with `Promise.all(patterns.map(take))`.
If you need to await and receive multiple actions in specific order, use multiple `await take()` instead.
```javascript
const [{ payload: articles }, { payload: users }] = await takeAllOf(['RECEIVE_ARTICLES', 'RECEIVE_USERS']);
```
#### takeOneOf
```typescript
const takeOneOf:
(patterns: Pattern
[]) => Promise>;
```
`takeOneOf` receives an array of patterns as its single argument, and returns a Promise which contains the first action matching with one of patterns.
Internally, `takeOneOf(patterns)` is the same with `Promise.race(patterns.map(take))`.
```javascript
const { type } = await takeOneOf(['FETCH_USER_SUCCESS', 'FETCH_USER_FAILURE']);
if (type === 'FETCH_USER_SUCCESS') {
// success
} else {
// failure
}
```
You might not need `takeOneOf`.
```javascript
const { type } = await take(/^FETCH_USER/);
```
### DO NOT OVERUSE
Avoid relying on props MUTATION!
This may cause unexpected behaviors, or make your components difficult to maintain.
```javascript
async componentDidMount() {
const { data } = this.props // this.props.data is mapped from redux store.
// dispatch an action and do some async call (e.g. xhr, fetch)
await take('RECEIVE_DATA'); // receive new data and update redux store by reducer
// DANGER: this.props.data is MUTATED!
console.assert(this.props.data === data); // Assertion failed!
}
```