【问题标题】:'dispatch' is not a function when argument to mapToDispatchToProps() in Redux当 Redux 中 mapToDispatchToProps() 的参数时,'dispatch' 不是函数
【发布时间】:2016-05-28 08:36:00
【问题描述】:

我是一个 javascript/redux/react 初学者,使用 redux、react-redux 和 react 构建一个小型应用程序。由于某种原因,当我将 mapDispatchToProps 函数与 connect(react-redux 绑定)结合使用时,我收到一个 TypeError 指示,当我尝试执行生成的 prop 时,调度不是一个函数。但是,当我将 dispatch 作为道具调用时(请参阅提供的代码中的 setAddr 函数),它可以工作。

我很好奇为什么会这样,在 redux 文档中的示例 TODO 应用程序中,mapDispatchToProps 方法的设置方式相同。当我在函数内使用 console.log(dispatch) 时,它说 dispatch 是类型对象。我可以继续以这种方式使用 dispatch,但在继续使用 redux 之前,我会更好地了解为什么会发生这种情况。我正在使用带有 babel-loaders 的 webpack 进行编译。

我的代码:

import React, { PropTypes, Component } from 'react';
import { connect } from 'react-redux';
import { setAddresses } from '../actions.js';
import GeoCode from './geoCode.js';
import FlatButton from 'material-ui/lib/flat-button';

const Start = React.createClass({
    propTypes: {
        onSubmit: PropTypes.func.isRequired
    },

    setAddr: function(){
        this.props.dispatch(
            setAddresses({
                pickup: this.refs.pickup.state.address,
                dropoff: this.refs.dropoff.state.address
            })
        )   

    },

    render: function() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-6">
                        <GeoCode ref='pickup' />
                    </div>
                    <div className="col-xs-6">
                        <GeoCode ref='dropoff' />
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-6">
                        <FlatButton 
                            label='Does Not Work'
                            onClick={this.props.onSubmit({
                                pickup: this.refs.pickup.state.address,
                                dropoff: this.refs.dropoff.state.address
                            })} 
                            />
                    </div>
                    <div className="col-xs-6">
                        <FlatButton 
                            label='Works'
                            onClick={this.setAddr} 
                            />
                    </div>
                </div>
            </div>
        );
    }
})

const mapDispatchToProps = (dispatch) => {
    return {
        onSubmit: (data) => {
            dispatch(setAddresses(data))
        }
    }
}

const StartContainer = connect(mapDispatchToProps)(Start)

export default StartContainer

干杯。

【问题讨论】:

  • 我遇到了这个问题,this 帮我解决了

标签: javascript reactjs redux react-redux


【解决方案1】:

如果你想使用mapDispatchToProps 而不使用mapStateToProps,只需使用null 作为第一个参数。

export default connect(null, mapDispatchToProps)(Start)

【讨论】:

  • 这就是我一直在寻找的。现在我知道我是否只想调度一些操作。
  • 这正是我一直在寻找的东西。感谢您提供完美的解决方案。如果我们不必在任何组件中使用 mapDispatchToProps 怎么办?我们必须以同样的方式处理这种情况吗?
  • 如果您不需要mapDispatchToProps,请不要将该参数添加到connectconnect(mapStateToProps)(MyComponent)
【解决方案2】:

您只是缺少connect 的第一个参数,即mapStateToProps 方法。摘自 Redux 待办事项应用程序:

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}

const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

【讨论】:

  • 这个方法是强制的吗?这个方法只是捕获状态,如果我们不需要这个方法怎么办?
  • @MuneemHabib 查看 inostia 的回答,了解如何在不需要时不提供此方法
【解决方案3】:

使用

const StartContainer = connect(null, mapDispatchToProps)(Start) 

而不是

const StartContainer = connect(mapDispatchToProps)(Start)

【讨论】:

    【解决方案4】:

    我通过交换参数解决了它,我正在使用

    export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)
    

    这是错误的。 mapStateToProps 必须是第一个参数:

    export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)
    

    现在听起来很明显,但可能会对某人有所帮助。

    【讨论】:

      【解决方案5】:

      我需要一个使用 React.Component 的示例,所以我将其发布:

      import React from 'react';
      import * as Redux from 'react-redux';
      
      class NavigationHeader extends React.Component {
      
      }
      
      const mapStateToProps = function (store) {
          console.log(`mapStateToProps ${store}`);
          return {
              navigation: store.navigation
          };
      };
      
      export default Redux.connect(mapStateToProps)(NavigationHeader);
      

      【讨论】:

        【解决方案6】:

        问题

        为了了解连接组件在您的代码中的行为,需要注意以下几点:

        connect 的 Arity 很重要:connect(mapStateToProps, mapDispatchToProps)

        React-Redux 使用第一个参数 mapStateToProps 和第二个参数 mapDispatchToProps 调用 connect

        因此,尽管您已经传入了 mapDispatchToProps,但 React-Redux 实际上将其视为 mapState,因为它是第一个参数。您仍然会在组件中获得注入的 onSubmit 函数,因为 mapState 的返回被合并到组件的 props 中。但这不是mapDispatch 应该被注入的方式。

        您可以使用mapDispatch 而不定义mapState。传入null 代替mapState,您的组件不会受到存储更改的影响。

        连接的组件默认接收dispatch,当没有提供mapDispatch

        此外,您的组件收到dispatch,因为它收到了null 的第二个位置mapDispatch。如果你正确传入mapDispatch,你的组件将不会收到dispatch

        常见做法

        上面回答了为什么组件会这样。虽然,通常的做法是使用mapStateToProps 的对象速记简单地传递动作创建者。并在组件的onSubmit 中调用它,即:

        import { setAddresses } from '../actions.js'
        
        const Start = (props) => {
          // ... omitted
          return <div>
            {/** omitted */}
            <FlatButton 
               label='Does Not Work'
               onClick={this.props.setAddresses({
                 pickup: this.refs.pickup.state.address,
                 dropoff: this.refs.dropoff.state.address
               })} 
            />
          </div>
        };
        
        const mapStateToProps = { setAddresses };
        export default connect(null, mapDispatchToProps)(Start)
        

        【讨论】:

          【解决方案7】:

          这个问题涵盖了一些人可能会陷入的陷阱,但没有在答案中解决,因为它在代码结构中略有不同,但返回完全相同的错误。

          这个错误在使用bindActionCreators而不传递dispatch函数时出现

          错误代码

          import someComponent from './someComponent'
          import { connect } from 'react-redux';
          import { bindActionCreators } from 'redux'
          import { someAction } from '../../../actions/someAction'
          
          const mapStatToProps = (state) => {
              const { someState } = state.someState
          
              return {
                  someState
              }
          };
          
          const mapDispatchToProps = (dispatch) => {
              return bindActionCreators({
                  someAction
              });
          };
          
          export default connect(mapStatToProps, mapDispatchToProps)(someComponent)
          

          固定代码

          import someComponent from './someComponent'
          import { connect } from 'react-redux';
          import { bindActionCreators } from 'redux'
          import { someAction } from '../../../actions/someAction'
          
          const mapStatToProps = (state) => {
              const { someState } = state.someState
          
              return {
                  someState
              }
          };
          
          const mapDispatchToProps = (dispatch) => {
              return bindActionCreators({
                  someAction
              }, dispatch);
          };
          
          export default connect(mapStatToProps, mapDispatchToProps)(someComponent)
          

          错误代码中缺少函数dispatch

          【讨论】:

            【解决方案8】:

            React-redux 'connect' 函数接受两个参数,第一个是 mapStateToProps,第二个是 mapDispatchToProps 检查下面的例子。

            export default connect(mapStateToProps, mapDispatchToProps)(Index); `

            如果我们不想从 redux 中检索状态,那么我们设置 null 而不是 mapStateToProps。

            export default connect(null, mapDispatchToProps)(Index);

            【讨论】:

              【解决方案9】:

              当您不提供mapDispatchToProps 作为第二个参数时,如下所示:

              export default connect(mapStateToProps)(Checkbox)
              

              然后您会自动将调度发送到组件的道具,因此您可以:

              class SomeComp extends React.Component {
                constructor(props, context) {
                  super(props, context);
                }
                componentDidMount() {
                  this.props.dispatch(ACTION GOES HERE);
                }
              ....
              

              没有任何 mapDispatchToProps

              【讨论】:

                【解决方案10】:

                我是这样使用的。它易于理解的第一个参数是 mapStateToProps,第二个参数是 mapDispatchToProps,最后与函数/类连接。

                const mapStateToProps = (state) => {
                  return {
                    todos: getVisibleTodos(state.todos, state.visibilityFilter)
                  }
                }
                
                const mapDispatchToProps = (dispatch) => {
                  return {
                    onTodoClick: (id) => {
                      dispatch(toggleTodo(id))
                    }
                  }
                }
                
                export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
                

                【讨论】:

                • 如果你没有第一个参数,那么只需传递 null / undefined 然后是第二个参数..
                【解决方案11】:

                有时在传递给连接时更改组件函数的顺序也会发生此错误。

                顺序错误:

                export default connect(mapDispatchToProps, mapStateToProps)(TodoList);
                

                正确顺序:

                export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
                

                【讨论】:

                  【解决方案12】:

                  我在写的时候遇到了这个问题:
                  导出默认连接(mapDispatchToProps,mapStateToProps)(SearchInsectsComponent); 代替 导出默认连接 (mapStateToProps,mapDispatchToProps)(SearchInsectsComponent);

                  【讨论】:

                    猜你喜欢
                    • 2017-10-31
                    • 1970-01-01
                    • 2017-04-30
                    • 2021-04-26
                    • 2017-06-09
                    • 1970-01-01
                    • 2016-12-19
                    • 2018-08-13
                    • 1970-01-01
                    相关资源
                    最近更新 更多