-
Notifications
You must be signed in to change notification settings - Fork 0
/
make-reducer.js
70 lines (65 loc) · 2.13 KB
/
make-reducer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
/**
* Base reducer for an api request, taking into account the action.key If it
* exists it will store in the state under that path. Allows for page caching.
*
* Uses the following actions:
* - invalidate/<actionName>
* - begin/<actionName>
* - end/<actionName>
*
* @param {object} op Options
* @param {string} op.name The action name to use as suffix
* @param {object} op.initialState Initial state to use. Used by the invalidate
* action
* @param {object} op.baseState The base state from where to get the needed
* properties.
*
* @example
* const resultsReducer = makeReducer({ name: 'results', initialState: {}, baseState: {} });
*/
export function makeReducer({ name: actionName, initialState, baseState }) {
// Reducer function.
const contexeedReducer = (state, action) => {
// The status to update depends on whether is a mutation or not.
const statusKey = action.isMutation ? 'mutationStatus' : 'status';
switch (action.type) {
case `invalidate/${actionName}`:
return initialState;
case `begin/${actionName}`: {
return {
...baseState,
...state,
[statusKey]: 'loading'
};
}
case `end/${actionName}`: {
// eslint-disable-next-line prefer-const
let st = {
...baseState,
...state,
receivedAt: action.receivedAt
};
if (action.error) {
st[statusKey] = 'failed';
st.error = action.error;
// The data remains to what was previously set. This allows to keep
// the data in the interface even if the request fails.
} else {
st[statusKey] = 'succeeded';
st.data = action.data;
st.error = null;
}
return st;
}
}
return state;
};
// Run the reducer and apply the state according to whether there's a key or
// not.
return (state, action) => {
const hasKey = typeof action.key !== 'undefined';
const stateSlice = hasKey ? state[action.key] : state;
const newState = contexeedReducer(stateSlice, action);
return hasKey ? { ...state, [action.key]: newState } : newState;
};
}