【问题标题】:Redux reducers as pure functionsRedux reducer 作为纯函数
【发布时间】:2019-11-22 06:12:53
【问题描述】:

我总是在 redux reducer 中这样初始化日期:

const initialState = {
  dateFilter: new Date()
}

const reducer = (state = initialState, action) => {
// reducer code
}

export default reducer;

我不确定我的做法是否正确,因为据我所知,reducer 必须是纯函数,而 new Date 不是纯函数。也许这更像是一个js问题,因为我不明白reducer函数是否在这里是纯的。

【问题讨论】:

  • 为什么觉得这个函数不纯?因为现在这个sn-p这个函数是空的,你怎么知道这个是不是纯的?
  • 我假设其他一切都是纯粹的,我没有在减速器代码中做任何new Date。问题是关于initialState。但是好的,我认为参数不会使函数不纯
  • 您的 initialState 仅被创建一次,如果未提供参数,则将其用作参数的后备。只要您不更改减速器的全局状态并始终返回新状态而不是更改先前的状态,您的函数就是纯函数。

标签: javascript reactjs redux


【解决方案1】:

只要您不在// reducer code 内做其他事情,这就是纯粹的 :)。例如再次调用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 + badd(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))

【讨论】:

  • 对不起,为什么?你能解释一下吗?
  • 通过执行副作用获得参数这一事实并不会使函数不纯。假设您有两个随机数 (a = Math.random(), b = Math.random())。它们以某种方式随机生成的事实并不能说明const add = (a, b) => a + b 不纯
  • 我认为,在无参数的情况下,函数只是纯 if initialState 保证不可变。
  • 也许我是新手,但我不明白纯函数和非纯函数之间的区别(从我的角度来看,这纯粹是技术性的),如果@YuryTarabanko 可以在他的回答中解释这一点,我会很感激
  • @GrecoJonathan Pure 函数是一个输出取决于输入的函数,它不会执行任何可观察到的副作用。想想说加法。 add(1, 2) 始终为 3 且未发射任何导弹。如果函数是纯函数,您可以安全地:缓存结果、重新排序或延迟调用、在相同参数上多次调用函数等等。纯函数的冒烟测试是“相同的输入产生相同的输出”。默认情况下,js 中的函数不需要是纯函数,通常很难保证它们是纯函数,因为 javascript 内置对象默认是可变的。
猜你喜欢
  • 1970-01-01
  • 2021-05-08
  • 2017-11-29
  • 2017-03-28
  • 1970-01-01
  • 2018-10-18
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
相关资源
最近更新 更多