根据 NgRx 文档,Reducers 和 Selectors 是纯函数。
“Reducer 是纯函数,因为它们对于给定的输入产生相同的输出。”
“因为选择器是纯函数,所以当参数匹配时可以返回最后的结果,而无需重新调用选择器函数。”
考虑以下简单示例
export const AppState = {
dataArray: []
}
// A Simple action that adds to the dataArray (created by Action creator)
export const addAction = createAction('Add to dataArray', props<{ data:number }>())
// Initial state of dataArray is an empty array
const initialDataArray = [];
// A simple reducer to get new state (created by Reducer creator)
// The new data element is simply added to the previous dataArray and a new Array is returned
export const dataArrayReducer = createReducer(initialDataArray,
on(addAction, (state, newData) => ([...state.dataArray, newData])))
// A selector to get the dataArray
export const selectDataArray = (state: AppState) => state.dataArray;
// Suppose we dispatch actions to the store
store.dispatch(addAction(1)); // Reducer will return state : { dataArray : [1] }
store.dispatch(addAction(1)); // Reducer will return state : { dataArray [1, 1] }
// Different states returned even though the input was the same Action with same props
const dataArray$ = store.pipe(select(selectDataArray)); // [1, 1]
store.dispatch(addAction(1));
const dataArray2$ = store.pipe(select(selectDataArray)); // [1, 1, 1]
// We get different values from the same selector.
正如我们所见,即使我们提供完全相同的参数,我们也会从Reducer 和Selector 获得不同的值。 那么它们如何才能被视为纯函数呢?
我错过了什么吗?我是否理解了纯函数的定义错误?
经过一番思考,我找到了问题的答案。
要记住的关键是,Reducers 和 Selectors 都将 State 作为除了其他参数之外的参数。 createReducer 和 createSelector 函数返回必须将状态传递给的Reducer 和Selector 函数。
因此,对于给定的状态,相同的参数将始终返回相同的值,这就是为什么它们是纯函数。
第一次调度 addAction 时状态为 { dataArray = [] } 第二次调度 addAction 时,状态为 { dataArray = [1] }
因此我们从Reducer得到不同的值。
对于选择器来说类似,第一次调用选择器时的状态是 { dataArray = [1, 1] } 第二次调用时状态为 { dataArray = [1, 1, 1] }.
因此选择器每次也返回不同的值。
Reducer 是纯函数:
// Initial state: an empty array
const initialDataArray: number[] = [];
// Reducer to add new data to the dataArray
const dataArrayReducer = createReducer(
initialDataArray,
on(addAction, (state, newData) => [...state, newData])
);