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

问题描述 投票:86回答:10

我是一个javascript / redux / react初学者用redux,react-redux和react做一个小应用程序。出于某种原因,当使用mapDispatchToProps函数与connect(react-redux binding)串联时,我收到一个TypeError,指示当我尝试执行生成的prop时,dispatch不是函数。当我将调度作为支柱调用时(参见提供的代码中的setAddr函数)它可以工作。

我很好奇为什么会这样,在redux文档中的示例TODO应用程序中,mapDispatchToProps方法的设置方式相同。当我在函数内部调试console.log(dispatch)时,它表示dispatch是type对象。我可以继续以这种方式使用调度,但在我继续使用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

干杯。

javascript reactjs redux react-redux
10个回答
159
投票

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

export default connect(null, mapDispatchToProps)(Start)


0
投票

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

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


0
投票

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

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

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

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


101
投票

你只是错过了connect的第一个参数,这是mapStateToProps方法。摘自Redux todo应用程序:

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)

17
投票

使用

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)

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


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

2
投票

问题

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

connect的Arity事项:connect(mapStateToProps, mapDispatchToProps)

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

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

你可以使用mapDispatch而不定义mapState。通过null代替mapState,您的组件将不会更改商店。

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

此外,你的组件收到dispatch,因为它收到nullmapDispatch的第二个位置。如果你正确传入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)

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


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

0
投票

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

订单不正确:

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

正确的顺序:

export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
© www.soinside.com 2019 - 2024. All rights reserved.