Skip to content

Commit

Permalink
Merge pull request #46 from sayag11/makeAsyncReducer-additions
Browse files Browse the repository at this point in the history
Added 'loaded' flag to makeAsyncReducer
  • Loading branch information
vzaidman authored Apr 7, 2019
2 parents 8dfaf67 + d0a6f4d commit f505df5
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 11 deletions.
18 changes: 15 additions & 3 deletions packages/redux-toolbelt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,7 @@ const state = undefined
asyncReducer(state, {type: '@@INIT'})
// ==> {
// loading: false,
// loaded: false,
// data: undefined
// }
```
Expand All @@ -366,6 +367,7 @@ const state = undefined
asyncReducer(state, {type: '@@INIT'})
// ==> {
// loading: false,
// loaded: false,
// results: []
// }
```
Expand All @@ -381,6 +383,7 @@ const state = {data: ['a']}
asyncReducer(state, asyncAction.success('b'))
// ==> {
// loading: false,
// loaded: true,
// data: ['a', 'b']
// }
```
Expand All @@ -403,6 +406,7 @@ const state = undefined
asyncReducer(state, {type: '@@INIT'})
// ==> {
// loading: false,
// loaded: false,
// counter: 0,
// status: 'offline'
// }
Expand All @@ -415,13 +419,15 @@ on state generically.

##### Request
When the reducer gets the `request` action it updates the `loading` field.
The 'loaded' field keeps its value.
```js
const asyncReducer = makeAsyncReducer(asyncAction)

const state = {loading: false, data: [1, 2, 3]}
asyncReducer(state, asyncAction())
// ==> {
// loading: true,
// loaded: state.loaded,
// data: [1, 2, 3]
// }
```
Expand All @@ -437,12 +443,14 @@ const state = {loading: false, data: [1, 2, 3]}
asyncReducer(state, asyncAction())
// ==> {
// loading: true,
// loaded: false,
// data: []
// }
```

##### Progress
When the reducer gets the `progress` action it's updating the `progress` field with the action's payload.
The 'loaded' field depends on the previous value - indicating if the data is already loaded

```js
const asyncReducer = makeAsyncReducer(asyncAction)
Expand All @@ -451,19 +459,21 @@ const state = {loading: true}
asyncReducer(state, asyncAction.progress(5))
// ==> {
// loading: true,
// loaded: state.loaded,
// progress: 5
// }
```

##### Success
When the reducer gets the `success` action is updates the `loading` to `true` and sets the `dataProp` field with the action's payload.
When the reducer gets the `success` action is updates the `loading` to `false`, the 'loaded' to 'true' and sets the `dataProp` field with the action's payload.

```js
const asyncReducer = makeAsyncReducer(asyncAction)
const state = {loading: true}
asyncReducer(state, asyncAction.success([1, 2, 3]))
// ==> {
// loading: false,
// loaded: true,
// 'data': [1, 2, 3]
// }
```
Expand All @@ -478,7 +488,8 @@ const asyncReducer = makeAsyncReducer(asyncAction, {
const state = {loading: true}
asyncReducer(state, asyncAction.success([1, 2, 3]))
// ==> {
// loading: false
// loading: false,
// loaded: true,
// }
```

Expand All @@ -492,7 +503,8 @@ const state = {loading: true}
asyncReducer(state, asyncAction.failure(`Server unreachable`))
// ==> {
// loading: false,
// error: 'Server unreachable'
// error: 'Server unreachable',
// loaded: state.loaded,
// }
```

Expand Down
24 changes: 16 additions & 8 deletions packages/redux-toolbelt/src/makeAsyncReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,39 @@ export default function makeAsyncReducer(actionCreator, options) {
options = Object.assign(defaults, options)

const defaultState = options.shouldSpread ?
{ error: undefined, loading: false, ...(options.defaultData || {}) } :
{ error: undefined, loading: false, [options.dataProp]: options.defaultData }
{ error: undefined, loading: false, loaded: false, ...(options.defaultData || {}) } :
{ error: undefined, loading: false, loaded: false, [options.dataProp]: options.defaultData }

return function (state = defaultState, { type, payload, meta }) {
switch (type) {
case actionCreator.TYPE:
return options.shouldSpread ?
{ loading: true, ...(options.defaultData || {}) } :
{ loading: true, [options.dataProp]: options.shouldDestroyData ? options.defaultData : state[options.dataProp] }
{
loading: true,
loaded: options.shouldDestroyData ? false : state.loaded,
...(options.defaultData || {}),
} :
{
loading: true,
loaded: options.shouldDestroyData ? false : state.loaded,
[options.dataProp]: options.shouldDestroyData ? options.defaultData : state[options.dataProp],
}
case actionCreator.success.TYPE: {
if (!options.shouldSetData){
return {loading: false}
return {loading: false, loaded: true}
}
const progress = state && state.progress === undefined ? {} : {progress: 0}
const data = typeof(options.dataGetter) === 'function' ?
options.dataGetter(state, {type, payload, meta}) : payload
return options.shouldSpread ?
{loading: false, ...progress, ...data} :
{loading: false, ...progress, [options.dataProp]: data}
{loading: false, loaded: true, ...progress, ...data} :
{loading: false, loaded: true, ...progress, [options.dataProp]: data}
}
case actionCreator.progress.TYPE:
return {...state, progress: payload}
case actionCreator.failure.TYPE:
return {
...(options.shouldDestroyDataOnError ? {} : state),
...(options.shouldDestroyDataOnError ? {loaded: false} : state),
loading: false,
error: options.shouldSetError ? payload : undefined,
}
Expand Down
6 changes: 6 additions & 0 deletions packages/redux-toolbelt/test/makeAsyncReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ test('default store', () => {
expect(state).toEqual({
error: undefined,
loading: false,
loaded: false,
data: undefined,
})
})
Expand All @@ -32,20 +33,23 @@ test('store with dataProp', () => {
expect(state).toEqual({
error: undefined,
loading: false,
loaded: false,
someDataProp: undefined,
})

store.dispatch(asyncAction())
state = store.getState()
expect(state).toEqual({
loading: true,
loaded: false,
someDataProp: undefined,
})

store.dispatch(asyncAction.success(['some-data']))
state = store.getState()
expect(state).toEqual({
loading: false,
loaded: true,
someDataProp: ['some-data'],
})
})
Expand All @@ -63,13 +67,15 @@ test('reducer with dataGetter', () => {
expect(state).toEqual({
error: undefined,
loading: false,
loaded: false,
data: ['a'],
})

store.dispatch(asyncAction.success('b'))
state = store.getState()
expect(state).toEqual({
loading: false,
loaded: true,
data: ['a', 'b'],
})

Expand Down

0 comments on commit f505df5

Please sign in to comment.