React:动作创建者不调用reducer

Kum*_*r R 3 javascript reactjs redux

我正在我的动作创建者中进行异步调用并使用结果调用我的reducer,但由于某种原因我无法理解减速器没有被调用.

actions.js(动作和动作创建者)

export const GET_FORMS = 'GET_FORMS'

export function getForms() {
  $.get("server url", function(result) {
   return {
    type: GET_FORMS,
    formlist: result.data.forms
   }   
  })
 }
Run Code Online (Sandbox Code Playgroud)

reducers.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
 }
}
Run Code Online (Sandbox Code Playgroud)

App.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)
Run Code Online (Sandbox Code Playgroud)

Nat*_*gen 12

这里有一些事情.

  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() { ... }
    }
    
    Run Code Online (Sandbox Code Playgroud)

    从$.getapi我们知道$.get返回一个jqXHR对象 ,而不是任何一种动作.所以你必须在自己的回调中使用结果 - 你不能只返回它.这是一个componentDidMount可能看起来像什么的例子(注意回调绑定this):

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

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

    这与你正在做的非常类似,除了你正在创建一个 - 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()'
    
    Run Code Online (Sandbox Code Playgroud)

    这个主要是一个样式选择,但我认为这是一个很好的模式:)对于多个动作创建者源对象,你可以这样做:

    export default connect(mapStateToProps, { ...FormActions, ...UserActions })(App);
    
    Run Code Online (Sandbox Code Playgroud)