156

我是一个 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

干杯。

4

12 回答 12

331

如果您想在mapDispatchToPropsmapStateToProps使用null第一个参数的情况下使用。

export default connect(null, mapDispatchToProps)(Start)

于 2016-08-01T21:43:26.240 回答
113

您只是缺少 的第一个参数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)
于 2016-02-16T21:26:27.927 回答
24

采用

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

代替

const StartContainer = connect(mapDispatchToProps)(Start)
于 2016-12-18T01:08:20.487 回答
7

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

export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)

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

export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)

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

于 2017-10-26T03:45:37.420 回答
3

我需要一个例子,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);
于 2016-07-18T08:29:31.813 回答
3

问题

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

事情的复杂性connectconnect(mapStateToProps, mapDispatchToProps)

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

因此,尽管您已经传入了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)
于 2018-10-09T17:04:44.310 回答
2

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

使用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错误代码中缺少该功能

于 2019-06-20T08:46:27.697 回答
1

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

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

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

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

于 2019-07-06T10:06:39.897 回答
0

当您不提供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

于 2018-02-16T13:21:21.237 回答
0

我是这样使用的。它易于理解的第一个参数是 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);
于 2018-09-11T13:08:41.737 回答
0

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

错误的顺序:

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

正确的顺序:

export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
于 2019-03-27T11:44:11.937 回答
0

我写的时候遇到了这个问题:
export default connect (mapDispatchToProps,mapStateToProps)(SearchInsectsComponent); 而不是导出默认连接(mapStateToProps,mapDispatchToProps)(SearchInsectsComponent);

于 2021-01-11T14:46:44.457 回答