web-dev-qa-db-ja.com

ReduxのmapToDispatchToProps()への引数の場合、 'dispatch'は関数ではありません

私は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

乾杯。

88
sully

mapDispatchToPropsを指定せずにmapStateToPropsを使用する場合は、最初の引数にnullを使用してください。

export default connect(null, mapDispatchToProps)(Start)

154
inostia

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)
101
Brandon

つかいます

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

の代わりに

const StartContainer = connect(mapDispatchToProps)(Start)
17
Ann

私は使用していた、議論を交換することによってそれを解決しました

export default connect(mapDispatchToProps, mapStateToProps)(Checkbox)

それは間違っています。 mapStateToPropsは最初の引数にする必要があります。

export default connect(mapStateToProps, mapDispatchToProps)(Checkbox)

それは今明白に聞こえますが、誰かを助けるかもしれません。

4
Amit Mittal

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);
3
Amio.io

問題

コード内のコネクテッドコンポーネントの動作を理解するために注意する点がいくつかあります。

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)
2
wgao19

このエラーは、connectに渡すときにComponent Functionの順序を変更したときにも発生することがあります。

間違った順序:

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

正しい順序:

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

その問題に取り組むかもしれない落とし穴がこの質問でカバーされていますが、それはコード構造でわずかに異なるが正確に同じエラーを返すので答えで扱われません。

このエラーは、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
TheyDontHaveIT

次のように、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なし

0
Serge Nikolaev

React-reduxの 'connect'関数は2つの引数を受け入れます。最初の引数はmapStateToProps、2番目の引数はmapDispatchToPropsですexの下のチェック。

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

Reduxから状態を取得したくない場合は、mapStateToPropsの代わりにnullを設定します。

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

0
Sachin Metkari

最初の引数は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);
0
Abdul Moiz