我是一个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
干杯。
如果你想在没有mapDispatchToProps
的情况下使用mapStateToProps
,只需使用null
作为第一个参数。
export default connect(null, mapDispatchToProps)(Start)
这个问题涵盖了一些可能陷入困境的陷阱,但在答案中没有解决,因为它在代码结构中略有不同但返回完全相同的错误。
使用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,检查下面的ex。
`export default connect(mapStateToProps, mapDispatchToProps)(Index);
如果我们不想从redux中检索状态,那么我们设置null而不是mapStateToProps。
export default connect(null, mapDispatchToProps)(Index);
你只是错过了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)
使用
const StartContainer = connect(null, mapDispatchToProps)(Start)
代替
const StartContainer = connect(mapDispatchToProps)(Start)
我通过交换参数来解决它,我正在使用
export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)
这是错的。 mapStateToProps
必须是第一个参数:
export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)
现在听起来很明显,但可能对某人有帮助。
我需要一个使用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);
为了理解代码中的连接组件行为,需要注意以下几点:
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
,因为它收到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)
当你不提供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
我这样使用..它易于理解的第一个参数是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);
有时在传递给连接时更改组件功能的顺序时也会发生此错误。
订单不正确:
export default connect(mapDispatchToProps, mapStateToProps)(TodoList);
正确的顺序:
export default connect(mapStateToProps,mapDispatchToProps)(TodoList);