-
Notifications
You must be signed in to change notification settings - Fork 4.2k
/
utils.ts
59 lines (54 loc) · 1.59 KB
/
utils.ts
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
/**
* External dependencies
*/
import type { AnyAction, Reducer } from 'redux';
/**
* Higher-order reducer creator which creates a combined reducer object, keyed
* by a property on the action object.
*
* @param actionProperty Action property by which to key object.
* @return Higher-order reducer.
*/
export const onSubKey =
< TState extends unknown, TAction extends AnyAction >(
actionProperty: string
) =>
(
reducer: Reducer< TState, TAction >
): Reducer< Record< string, TState >, TAction > =>
( state: Record< string, TState > = {}, action ) => {
// Retrieve subkey from action. Do not track if undefined; useful for cases
// where reducer is scoped by action shape.
const key = action[ actionProperty ];
if ( key === undefined ) {
return state;
}
// Avoid updating state if unchanged. Note that this also accounts for a
// reducer which returns undefined on a key which is not yet tracked.
const nextKeyState = reducer( state[ key ], action );
if ( nextKeyState === state[ key ] ) {
return state;
}
return {
...state,
[ key ]: nextKeyState,
};
};
/**
* Normalize selector argument array by defaulting `undefined` value to an empty array
* and removing trailing `undefined` values.
*
* @param args Selector argument array
* @return Normalized state key array
*/
export function selectorArgsToStateKey( args: unknown[] | null | undefined ) {
if ( args === undefined || args === null ) {
return [];
}
const len = args.length;
let idx = len;
while ( idx > 0 && args[ idx - 1 ] === undefined ) {
idx--;
}
return idx === len ? args : args.slice( 0, idx );
}