コネクトw / Reduxを使用してthis.propsから簡単なディスパッチを取得する方法?


107

接続する単純なReactコンポーネントがあります(単純な配列/状態をマッピングします)。ストアのコンテキストを参照しないようにするために、小道具から直接「ディスパッチ」を取得する方法が欲しいのですが。他の人がこのアプローチを使用しているのを見ましたが、何らかの理由でこれにアクセスできません:)

これは私が現在使用している各npm依存関係のバージョンです

"react": "0.14.3",
"react-redux": "^4.0.0",
"react-router": "1.0.1",
"redux": "^3.0.4",
"redux-thunk": "^1.0.2"

これは、接続メソッドを持つコンポーネントです

class Users extends React.Component {
    render() {
        const { people } = this.props;
        return (
            <div>
                <div>{this.props.children}</div>
                <button onClick={() => { this.props.dispatch({type: ActionTypes.ADD_USER, id: 4}); }}>Add User</button>
            </div>
        );
    }
};

function mapStateToProps(state) {
    return { people: state.people };
}

export default connect(mapStateToProps, {
    fetchUsers
})(Users);

レデューサーを見る必要がある場合(エキサイティングなものはありませんが、ここにあります)

const initialState = {
    people: []
};

export default function(state=initialState, action) {
    if (action.type === ActionTypes.ADD_USER) {
        let newPeople = state.people.concat([{id: action.id, name: 'wat'}]);
        return {people: newPeople};
    }
    return state;
};

ルーターがどのように再構成されているかを確認する必要がある場合

const createStoreWithMiddleware = applyMiddleware(
      thunk
)(createStore);

const store = createStoreWithMiddleware(reducers);

var Route = (
  <Provider store={store}>
    <Router history={createBrowserHistory()}>
      {Routes}
    </Router>
  </Provider>
);

更新

接続で自分のディスパッチを省略した場合(現在はfetchUsersを表示しています)、ディスパッチを解放します(これが非同期アクションのあるセットアップが通常どのように機能するかどうかはわかりません)。人々は混合して一致しますか、それとも全部ですか、それとも何ですか?

[mapDispatchToProps]

回答:


280

デフォルトmapDispatchToPropsはですdispatch => ({ dispatch })
あなたが二番目の引数を指定しないのであればconnect()、あなたが得るよdispatch、あなたのコンポーネントで小道具として注入。

カスタム関数をに渡すmapDispatchToPropsと、その関数を使用して何でも実行できます。
いくつかの例:

// inject onClick
function mapDispatchToProps(dispatch) {
  return {
    onClick: () => dispatch(increment())
  };
}

// inject onClick *and* dispatch
function mapDispatchToProps(dispatch) {
  return {
    dispatch,
    onClick: () => dispatch(increment())
  };
}

入力を節約するために、bindActionCreators()これを有効にするReduxの入力をいくつか提供します。

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return {
    onPlusClick: () => dispatch(increment()),
    onMinusClick: () => dispatch(decrement())
  };
}

これに:

import { bindActionCreators } from 'redux';

// injects onPlusClick, onMinusClick
function mapDispatchToProps(dispatch) {
  return bindActionCreators({
    onPlusClick: increment,
    onMinusClick: decrement
  }, dispatch);
}

または、プロップ名がアクション作成者名と一致する場合はさらに短くなります。

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

dispatch手で追加したい場合は、次のようにします。

// injects increment, decrement, and dispatch itself
function mapDispatchToProps(dispatch) {
  return {
    ...bindActionCreators({ increment, decrement }), // es7 spread syntax
    dispatch
  };
}

これを行うべきかどうかについての公式なアドバイスはありません。connect()通常、Redux対応コンポーネントとRedux非対応コンポーネントの間の境界として機能します。これが、通常バインドされたアクションの作成者との両方を挿入することは意味がないと私たちが感じる理由dispatchです。ただし、これを行う必要があると感じた場合は、遠慮なく行ってください。

最後に、現在使用しているパターンは、を呼び出すよりもさらに短いショートカットですbindActionCreators。行うのがreturn bindActionCreatorsだけの場合は、これを行う代わりに呼び出しを省略できます。

// injects increment and decrement
function mapDispatchToProps(dispatch) {
  return bindActionCreators({ increment, decrement }, dispatch);
}

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

このように書くことができます

export default connect(
  mapStateToProps,
  { increment, decrement } // injects increment and decrement
)(App);

ただし、渡すなど、よりカスタムなものが必要なときはいつでも、この短い構文をあきらめる必要がありますdispatch


2
@DanAbramov btwはbindActionCreators(actionCreators, dispatch)オプションの2番目のパラメーターですか?私はあなたのコードで// es7 spread syntax行に気づきました、それdispatchは渡されていませんbindActionCreators
yonasstephen

内部増分メソッドとは何ですか?
Khurshid Ansari、

es7スプレッド構文は function mapDispatchToProps(dispatch) { return { ...bindActionCreators({ increment, decrement }), dispatch }; }
ブラック

6

通常は、好きなものに基づいて組み合わせることができます。

あなたはでき渡しますdispatchそれがあなたが望むものであれば、あなたは小道具としてます:

export default connect(mapStateToProps, (dispatch) => ({
    ...bindActionCreators({fetchUsers}, dispatch), dispatch
}))(Users);

fetchUsers(非同期関数として)どのように使用されるのかはわかりませんが、通常は次のようなものbindActionCreatorsを使用しますディスパッチ自動バインドするを使用dispatchし、接続されたコンポーネントで直接使用することを心配する必要はありません。

dispatchディレクトリソートを使用すると、ダムのないステートレスコンポーネントとredux が結合されます。これにより、移植性が低下する可能性があります。


3
あなたが提案しているものは機能しません。fetchUsersプロップとしてアンバインドされます。ショートカット表記は、オブジェクトを2番目の引数として渡す場合にのみ機能します。関数を渡すときは、bindActionCreators自分自身を呼び出す必要がありますdispatch => ({ ...bindActionCreators({ fetchUsers }, dispatch), dispatch })
Dan Abramov、2015

bindActionCreatorsでディスパッチを直接拡散して渡すのはなぜですか?dispatch => ( bindActionCreators({ dispatch, fetchUsers }, dispatch))
user3711421

2

dispatch一部として受け継ぐこともできますがdispatchToPropsstoreまたはへのアクセスを避けることをお勧めしますdispatch、コンポーネントコンポーネント内からの直接します。接続の2番目の引数でバインドされたアクションクリエーターを渡すことで、より良いサービスが提供されるようですdispatchToProps

私がここに投稿した例を参照してくださいhttps://stackoverflow.com/a/34455431/2644281この方法で「すでにバインドされたアクションクリエーター」を渡す方法は、コンポーネントがストア/ディスパッチを直接認識したり依存したりする必要がないようにする方法です。 。

簡潔に申し訳ありません。詳細を更新します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.