'dispatch' 不是 Redux 中 mapToDispatchToProps() 参数时的函数

'dispatch' is not a function when argument to mapToDispatchToProps() in Redux

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

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

我的代码:

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

干杯。

您只是缺少 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)

我需要一个使用 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);

如果您想在没有 mapStateToProps 的情况下使用 mapDispatchToProps,只需使用 null 作为第一个参数。

export default connect(null, mapDispatchToProps)(Start)

使用

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

而不是

const StartContainer = connect(mapDispatchToProps)(Start)

我通过交换参数解决了这个问题,我使用的是

export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)

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

export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)

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

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

export default connect(mapStateToProps)(Checkbox)

然后您将自动获得对组件 props 的调度,因此您可以:

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

没有任何 mapDispatchToProps

我是这样使用的..它很容易理解第一个参数是 mapStateToProps 第二个参数是 mapDispatchToProps 最后连接到 function/class。

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);

问题

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

connect 的性质:connect(mapStateToProps, mapDispatchToProps)

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

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

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

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

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

常见做法

以上回答了为什么组件会这样。虽然,通常的做法是使用 mapStateToProps 的对象 shorthand 简单地传入动作创建者。并在组件的 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)

有时,当您在传递给连接时更改组件函数的顺序时,也会出现此错误。

顺序不正确:

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

正确顺序:

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

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

使用 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

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

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

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

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

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

你在最后一句话中漏掉了。由于我们没有 mapStateToProps,所以声明如下

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