反应:动作创建者不调用化简器

React : Action creator not calling reducer

本文关键字:调用 创建者 反应      更新时间:2023-09-26

我正在我的动作创建器中进行异步调用并使用结果调用我的化简器,但由于某种原因,我无法理解没有调用化简器。

操作.js(操作和操作创建者(

export const GET_FORMS = 'GET_FORMS'
export function getForms() {
  $.get("server url", function(result) {
   return {
    type: GET_FORMS,
    formlist: result.data.forms
   }   
  })
 }

减速器.js

import { GET_FORMS } from '../actions/actions'
export default function formAction(state = {forms:[]}, action) {
  console.log("received action"+action.type)
  switch (action.type) {
    case GET_FORMS:
      console.log("Action:"+action);
      return Object.assign({},state,{
       forms:action.formlist
      })
   default:
    return state
 }
}

应用.js

import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom';
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import auth from '../auth'
import FormTable from '../components/FormTable'
import * as FormActions from '../actions/actions'

class App extends Component {
 constructor(props) {
  super(props);
  this.state = {forms: []};
 }
 componentDidMount() {
  // for some reason if i write this.props.actions.getForms () i get an error
  // Uncaught Error: Actions must be plain objects. Use custom middleware for 
  // async actions.
  FormActions.getForms();
 }
 render() {
  const {forms,actions} = this.props
  console.log(forms);
  return (
    <FormTable results={forms} actions = {actions} /> 
  )
 }
}
App.PropTypes = {
  forms: PropTypes.array.isRequired
}
function mapStateToProps() {
 const {
  forms:forms
 } = {forms:[]}
 return {
  forms
 }
}
function mapDispatchToProps(dispatch) {
 return {
  actions: bindActionCreators(FormActions, dispatch)
 }
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(App)
这里有

几件事。

  1. 操作创建者不会返回它正在创建的操作。 $.get 不会返回操作,因此将其映射到 dispatch 效率不高。

    合理地,这可能会导致对如何从异步操作创建者返回操作感到困惑。由于它是异步的,因此本质上它无法返回最终结果(除非您使用 es7 async await (。您尝试的模式与此相同:

    class App extends Component {
      ...
      componentDidMount() {
        // Instead of calling getForms, do the same directly
        $.get(url, function(res) {
          return { type: GET_FORMS, forms: res };
        });
      }
      render() { ... }
    }
    

    $.get api 我们知道$.get返回一个jqXHR对象,而不是任何类型的操作。所以你必须在回调中使用结果本身 - 你不能只返回它。下面是一个示例,说明componentDidMount可能看起来像什么样子(请注意,回调绑定到this(:

    componentDidMount() {
      $.get(url, function(res) {
        this.props.dispatch({ type: GET_FORMS, forms: res });
      }.bind(this))
    }
    
  2. 在组件或操作创建器中执行异步是一种反模式,或者至少不鼓励这样做。在本例中,您将在动作创建器中定义异步,这很棒。但是你也在执行异步操作,这很糟糕。相反,您应该使用某种中间件来处理异步操作。中间件只是在调度后执行操作并对其执行操作的功能,为此目的最常见的是 redux-thunk .使用 redux-thunk ,您只需返回一个接受dispatch作为参数的函数。在本例中,动作创建者将如下所示:

    export function getForms() {
      return function(dispatch) {
        $.get(url, function(result) {
          dispatch({ type: GET_FORMS, forms: result });
        })
      }
    }
    

    这与你已经在做的事情非常相似,只是你正在创建一个thunk - 它只是一个定义另一个函数以供以后执行的函数 - 而不是现在实际执行异步操作,你正在定义它以便稍后执行。

  3. 你实际上并没有调度任何东西。

    最容易解决的问题,但绝对是一个障碍:)在 componentDidMount 中,您正在调用已导入的动作创建者,但不会调用dispatch 。虽然你已经完成了50%的路程,因为你把动作创造者传给了connect,但即使你这样做了,你也没有把connect传递到道具的绑定动作创造者称为绑定的动作创造者——你称之为未绑定的。

    所以与其打电话给FormActions.getForms(),不如叫this.props.actions.formActions()。前者不受约束,但后者受约束。调用后者与执行this.props.dispatch(FormActions.getForms())相同。

  4. 最后:在这种情况下,您不需要定义mapDispatchToProps。您可以将对象传递给该参数 connect 。见下文:

    // Instead of this
    export default connect(mapStateToProps, mapDispatchToProps)(App);
    // do this:
    export default connect(mapStateToProps, FormActions)(App);
    // creates the bound action creator 'this.props.getForms()'
    

    这个主要是一种风格选择,但我认为这是一个很好的模式:)对于多动作创建器源对象,您可以执行以下操作:

    export default connect(mapStateToProps, { ...FormActions, ...UserActions })(App);
    

你应该使用 redux-thunk 中间件:https://github.com/gaearon/redux-thunk

基本上就像您的代码一样 - 您没有返回符合 FSA 的操作(实际上现在没有返回任何内容(。您需要抛出调度,然后返回承诺的结果。

有关异步动作创建者的更多信息,请点击此处:http://redux.js.org/docs/advanced/AsyncActions.html