我总是初始化 redux reducer 中的日期,这样做:
const initialState = {
dateFilter: new Date()
}
const reducer = (state = initialState, action) => {
// reducer code
}
export default reducer;
我不确定我是否以正确的方式这样做,因为据我了解, reducer 必须是纯函数,而 new Date 不是纯函数。也许这更像是一个js问题,因为我不明白这里的reducer函数是否是纯粹的。
最佳答案
只要您不在 //reducer 代码
中执行其他操作,它就是纯粹的:)。例如再次调用new Date
(如第二个示例)
const initialState = {
dateFilter: new Date()
}
const reducer = (state = initialState, action) => {
switch(action.type) {
default: return state
}
}
console.log(`Reducer is ${
reducer(undefined, {type: '@@INIT'}) === reducer(undefined, {type: '@@INIT'})
? 'pure'
: 'not pure'}`)
这个不是
const initialState = () => ({
dateFilter: new Date()
})
const reducer = (state = initialState(), action) => {
switch(action.type) {
default: return state
}
}
console.log(`Reducer is ${
reducer(undefined, {type: '@@INIT'}) === reducer(undefined, {type: '@@INIT'})
? 'pure'
: 'not pure'}`)
UPD
正如 @spender 提到的,initialState
必须是不可变的。这在 javascript 中很难保证,因为默认情况下对象和日期都是可变的。为了保证不变性,可以使用
const initialState = Object.freeze({ // freeze the object
dateFilter: Date.now() // use immutable number instead of Date instance
})
还有 wiki 的 TLDR
纯函数是一种输出依赖于输入的函数,并且不执行任何可观察到的副作用。想想加法 const add = (a, b) => a + b
add(1, 2)
总是 3
并且没有导弹被推出。如果函数是纯函数,您可以安全:缓存结果、重新排序或延迟调用、对相同参数多次调用函数等等。
add(1, 2)
可以替换为 3。如果一个函数说计算它被调用的次数,那是不可能的。add(add(1,2), add(2,3))
您可以先执行add(1, 2)
然后add(2 , 3)
或反之亦然。如果一个函数说记录到控制台,这是不可能的。- 等等。
对纯函数的冒烟测试是“相同的输入产生相同的输出”。
不幸的是(或者幸运的是:))默认情况下,js 中的函数不需要是纯函数,并且通常很难保证它们是纯函数,因为 javascript 内置对象默认情况下是可变的。
即使是上面的 add 函数也可能会产生副作用,因此您必须对纯度定义持保留态度。
const add = (a, b) => a + b
const a = {
_i: 1,
valueOf() {
console.log('Missiles launched')
return this._i++;
}
}
console.log(add(a, 1), add(a, 1))
关于javascript - Redux reducer 作为纯函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57007601/