私はJavascript/redux/reactの初心者で、reducex、react-redux、およびreactを使用して小さなアプリケーションを構築しています。何らかの理由で、mapDispatchToProps関数をconnectと同時に使用すると(react-reduxバインディング)、結果のpropを実行しようとするとdispatchが関数ではないことを示すTypeErrorを受け取ります。ただし、propをdispatchとして呼び出すと(提供されているコードのsetAddr関数を参照)、正常に機能します。
これがなぜなのか私は興味があります、reduxのドキュメントの例のTODOアプリでmapDispatchToPropsメソッドが同じように設定されています。関数内でconsole.log(dispatch)を実行すると、dispatchはtypeオブジェクトです。私はこの方法でディスパッチを使い続けることができますが、私はreduxでこれ以上続ける前になぜこれが起こっているのかを知っている方が良いと感じるでしょう。私はコンパイルするためにバベルローダー付きの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)
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
のアリティ:connect(mapStateToProps, mapDispatchToProps)
React-Reduxは、最初の引数connect
と2番目の引数mapStateToProps
を付けてmapDispatchToProps
を呼び出します。
そのため、あなたはmapDispatchToProps
を渡しましたが、React-Reduxはそれを最初の引数であるので実際にはmapState
として扱います。 onSubmit
の戻り値はコンポーネントの小道具にマージされるため、注入されたmapState
関数はコンポーネント内に残ります。しかし、それはmapDispatch
がインジェクトされる方法ではありません。
mapDispatch
を定義せずにmapState
を使用することができます。 null
の代わりにmapState
を渡すと、コンポーネントはストアの変更の対象になりません。
dispatch
が指定されていない場合、接続先コンポーネントはデフォルトでmapDispatch
を受け取ります
また、コンポーネントはdispatch
の2番目の位置に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)
このエラーは、connectに渡すときにComponent Functionの順序を変更したときにも発生することがあります。
間違った順序:
export default connect(mapDispatchToProps, mapStateToProps)(TodoList);
正しい順序:
export default connect(mapStateToProps,mapDispatchToProps)(TodoList);
その問題に取り組むかもしれない落とし穴がこの質問でカバーされていますが、それはコード構造でわずかに異なるが正確に同じエラーを返すので答えで扱われません。
このエラーは、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
がありませんでした
次のように、2番目の引数として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なし
React-reduxの 'connect'関数は2つの引数を受け入れます。最初の引数はmapStateToProps、2番目の引数はmapDispatchToPropsですexの下のチェック。
export default connect(mapStateToProps, mapDispatchToProps)(Index);
`
Reduxから状態を取得したくない場合は、mapStateToPropsの代わりにnullを設定します。
export default connect(null, mapDispatchToProps)(Index);
最初の引数はmapStateToProps、2番目の引数は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);