重构“withReducer”:异步reducer函数调用的理由

时间:2017-01-07 12:31:21

标签: javascript reactjs recompose

我正在使用rededcer HOC并注意到这种行为: 在单击处理程序上调用此方法,例如:

import React from 'react'
import { withReducer } from 'recompose'
import { compose } from 'ramda'

export default compose(
  withReducer('state', 'dispatch', (state, { value }) => {
    console.log(value)
    return { ...state, value }
  }, { value: 'zero' })
)((props) => {
  const { dispatch, state } = props,
    onClick = () => {
      console.log('Hello')
      dispatch({ value: 'one' })
      dispatch({ value: 'two' })
      dispatch({ value: 'three' })
      console.log('World')
    }
  return (
    <div>
      <div>{state.value}</div>
      <button onClick={onClick}>Click me</button>
    </div>
  )
})

它会产生

  

您好

     

世界

     

一个

     

2

     

3

这意味着reduce函数是异步调用的。 将其称为异步而不是立即将更改应用于存储的理由是什么?

2 个答案:

答案 0 :(得分:4)

reducer是异步调用的,因为我们只能使用setState来更新树,而setState是异步的。

如果我们同步调用reducer,我们需要在某处保存新状态,然后调用setState并从我们保存它的位置异步获取新状态。最后,您的树仍然会异步更新。

这就是为什么重构withReducer()与redux略有不同。您可以认为withReducer是redux + react-redux的connect()的简化版本。

答案 1 :(得分:3)

在这种情况下,dispatch实际上是vanilla API方法setState的包装器。

React异步实现setState,因为出于性能原因,状态转换有时会被批处理。

根据React docs

  

setState()不会立即改变this.state但会创建挂起状态转换....无法保证对setState的调用进行同步操作,并且可以对调用进行批处理以获得性能提升。