@wordpress/data
Version:
Data module for WordPress.
53 lines (49 loc) • 1.41 kB
text/typescript
/**
* 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.
*
* @example
* ```js
* import { keyedReducer } from '@wordpress/data';
*
* const itemsByContext = keyedReducer( 'context' )( ( state = [], action ) => {
* switch ( action.type ) {
* case 'ADD_ITEM':
* return [ ...state, action.item ];
* }
* return state;
* } );
* ```
*/
export const keyedReducer =
< 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,
};
};