使用 redux saga 时等待 redux 动作完成调度

Wait for redux action to finish dispatching when using redux saga

我有一个运行良好的 redux saga 设置。我的任务之一是创建一个新订单,然后一旦创建,我想用更新后的状态做事。

// this.props.userOrders = []

dispatch(actions.createOrder(object))

doSomethingWith(this.props.userOrders)

由于 createOrder 操作触发了调用 API 的 redux saga,因此存在延迟,因此在调用我的函数 doSomethingWith 之前 this.props.userOrders 不会更新。我可以设置超时,但这似乎不是一个可持续的想法。

我在 Stack Overflow 上阅读了类似的问题,并尝试在相关的地方实施这些方法,但我似乎无法让它发挥作用。我希望我的代码下面有人可以只添加几行就可以做到这一点。

以下是相关的其他文件:

actions.js

export const createUserOrder = (data) => ({ 类型:'CREATE_USER_ORDER', 数据 })

Sagas.js

function * createUserOrder () {
  yield takeEvery('CREATE_USER_ORDER', callCreateUserOrder)
}

export function * callCreateUserOrder (newUserOrderAction) {
  try {
    const data = newUserOrderAction.data
    const newUserOrder = yield call(api.createUserOrder, data)
    yield put({type: 'CREATE_USER_ORDER_SUCCEEDED', newUserOrder: newUserOrder})
  } catch (error) {
    yield put({type: 'CREATE_USER_ORDER_FAILED', error})
  }
}

Api.js

export const createUserOrder = (data) => new Promise((resolve, reject) => {
  api.post('/userOrders/', data, {headers: {'Content-Type': 'application/json'}})
    .then((response) => {
      if (!response.ok) {
        reject(response)
      } else {
        resolve(data)
      }
    })
})

订单减速器:

case 'CREATE_USER_ORDER_SUCCEEDED':
   if (action.newUserOrder) {
      let newArray = state.slice()
      newArray.push(action.newUserOrder)
          return newArray
       } else {
       return state
   }

这感觉就像 XY Problem。你不应该 "waiting" 在任何时候都在组件的生命周期函数/事件处理程序中,而是利用商店的当前状态。

如果我没理解错的话,这是你当前的流程:

You dispatch an action CREATE_USER_ORDER in your React component. This action is consumed by your callCreateUserOrder saga. When your create order saga is complete, it dispatches another "completed" action, which you already have as CREATE_USER_ORDER_SUCCEEDED.

您现在应该添加的是正确的 reducer/selector 来处理您的 CREATE_USER_ORDER_SUCCEEDED:

CREATE_USER_ORDER_SUCCEEDED 操作应由您的减速器处理以创建一个新状态,其中填充了您状态中的某些 "orders" 属性。这可以通过选择器直接连接到您的组件,此时您的组件将被重新渲染并填充 this.props.userOrders


示例:

分量

class OrderList extends React.PureComponent {
  static propTypes = {
    userOrders: PropTypes.array.isRequired,
    createOrder: PropTypes.func.isRequired,
  }

  addOrder() {
    this.props.createOrder({...})
  }

  render() {
    return (
      <Wrapper>
        <Button onClick={this.addOrder}>Add Order</Button>
        <List>{this.props.userOrders.map(order => <Item>{order.name}</Item>)}</List>
      </Wrapper>
    )
  }
}

const mapStateToProps = state => ({
  userOrders: state.get('userOrders'),
})

const mapDispatchToProps = {
  createOrder: () => ({ type: 'CREATE_ORDER', payload: {} }),
}

export default connect(mapStateToProps, mapDispatchToProps)(OrderList)

减速器

case 'CREATE_USER_ORDER_SUCCEEDED':
  return state.update('userOrders',
    orders => orders.concat([payload.newUserOrder])
  )

如果您确实需要副作用,请将这些副作用添加到您的 saga 中,或者创建一个采取 SUCCESS 操作的新 saga。