Redux: Reactコンポーネントファイルからstore.dispatch()を呼び出しますか?

作成日 2015年10月19日  ·  10コメント  ·  ソース: reduxjs/redux

これがすでに解決されているものである場合はお詫び申し上げますが、問題のキーワード検索では何の役にも立ちませんでした。

コンポーネントファイルからstore.dispatch(someAction)を呼び出したい場合、 storeインスタンスにアクセスする正しい方法は何ですか?

現在、次の機能がありますが、それが正しいアプローチかどうかはわかりません。

index.jsx:

...
const store = applyMiddleware(
  loggingMiddleware, // log every action
  thunk // making API requests from actions
)(createStore)(reducer);

export {
  store
};
...

Controls.jsx

import {store} from './index.jsx';
import * as actions from './actions';
...
let clickHandler = function(node, data) {
  store.dispatch(actions.nodeClicked(data))
}
export const Controls = React.createClass({
  render: function() {
    // React component gets rendered, and it passes the clickHandler to a 
    // function that attaches it to a D3 visualization
  }
});

このようなストアのエクスポート/インポートに問題はありますか? Reactコンポーネントの一部としてクリックハンドラーを作成してthis.context.storeを呼び出すこともできると思いますが、実際には、D3ビジュアライゼーションに渡されるイベントハンドラーは約12種類あるため、これは実際には実用的ではありません。状況。

question

最も参考になるコメント

このようなストアのエクスポート/インポートに問題はありますか?

サーバー上のリクエストごとに異なるstoreインスタンスが必要なため、サーバー上でアプリをレンダリングする場合、これは機能しません。 そのため、ドキュメントではこのアプローチを推奨していません。

代わりにこれをしないのはなぜですか?

import { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from './actions';

let createHandlers = function(dispatch) {
  let onClick = function(node, data) {
    dispatch(actions.nodeClicked(data))
  };

  return {
    onClick,
    // other handlers
  };
}

class Controls extends Component {
  constructor(props) {
    super(props);
    this.handlers = createHandlers(this.props.dispatch);
  }

  render() {
    // pass this.handlers anywhere you'd like
  }
}

export default connect()(Controls);

全てのコメント10件

コンポーネントにディスパッチをバインドするためのヘルパーメソッドについては、 https://github.com/rackt/react-reduxを確認して

具体的には、 https://redux.js.org/docs/basics/UsageWithReact.htmlから

connect()呼び出しでラップされたコンポーネントは、小道具としてディスパッチ関数を受け取り、グローバル状態から必要な状態を受け取ります。

  • コンテンツが存在しなくなった関連ページへの新しいリンクでコメントを更新

このようなストアのエクスポート/インポートに問題はありますか?

サーバー上のリクエストごとに異なるstoreインスタンスが必要なため、サーバー上でアプリをレンダリングする場合、これは機能しません。 そのため、ドキュメントではこのアプローチを推奨していません。

代わりにこれをしないのはなぜですか?

import { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from './actions';

let createHandlers = function(dispatch) {
  let onClick = function(node, data) {
    dispatch(actions.nodeClicked(data))
  };

  return {
    onClick,
    // other handlers
  };
}

class Controls extends Component {
  constructor(props) {
    super(props);
    this.handlers = createHandlers(this.props.dispatch);
  }

  render() {
    // pass this.handlers anywhere you'd like
  }
}

export default connect()(Controls);

@gaearon見栄えがいい、ありがとう!

@gaearon実際、試してthis.props.dispatch undefinedを取得しています。

私のコードの関連部分:

import React from 'react';
import {Component} from 'react';
import {connect} from 'react-redux';
import * as vizActions from './vizActions';
import viz from './lib/viz';

let createHandlers = function(dispatch) {
  return {
    click: function(DOMNode, data) {
        // Getting undefined here
        dispatch(vizActions.setSelectedNode(data));
    }
  };
}

class Viz extends Component {
  constructor(props) {
    super(props);
    console.log(this.props.dispatch); // <- Getting undefined here
    // Passing the redux dispatch to be used in handlers function
    this.handlers = createHandlers(this.props.dispatch);
  }

  componentDidMount() {
    // Create Viz
  }

  componentDidUpdate() {
    // Update Viz Data, passing in this.handlers
  }

  render() {
    return <div id="viz"></div>;
  }
};


function mapStateToProps(state) {
  return {
    // Pass the network used for the viz as a prop
    network: state.get('visualization').get('network')
  };
}

export const VizContainer = connect(mapStateToProps, vizActions)(Viz);

しかし、別の問題(https://github.com/rackt/redux/issues/239)を読んだ後、私は私が実際に私の行動を結合していますことに気づいthis.props経由でconnect()私ができるので、 createHandlers()を呼び出すときに、必要なアクションを渡すだけです。 おそらくこれは最善のアプローチではありませんが、現在は機能しています。

...
let createHandlers = function(action) {
  return {
    click: function(DOMNode, data) {
                // This works now
        action(data);
    }
  };
}

class Viz extends Component {
  constructor(props) {
    super(props);
    // Passing the redux dispatch to be used in handlers function
    this.handlers = createHandlers(this.props.setSelectedNode); // passing action creator function
  }
...

実際、試してみたところ、this.props.dispatchが未定義になっています。

あなたは私が投稿したコードを実行していないからです。 私が投稿したコードでは、 connectは2番目のパラメーターを受け取りませんvizActions渡します。 そのため、 dispatch取得できません。 connect通話からvizActionsを削除すると、それを取得できます。

どちらのアプローチも同等ですが、自分に最適な方法を選択してください。

:+1:わかりました、それは今では理にかなっています。 助けてくれてありがとう!

ちょっとパーティーに遅れましたが、後で誰か(私を含む)を助ける場合に備えて返信します。
カスタムmapDispatchToPropsが必要な場合(接続に渡される2番目のパラメーター)、キーの1つとしてdispatchを明示的に追加します。

const mapDispatchToProps = (dispatch) => {
  return {
    dispatch,

    // ... other custom mapped dispatch functions ...
    myFunction: (myParam) => {
      dispatch(State.Actions...)
    },
  }
}

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

こんにちは。 私もこの問題を抱えています。
@gaearon 、ご指導
this.handlers使用方法がわかりません。ユーザーがカードをクリックすると、そのカードIDが親のコンポーネントに送信され、アクションが実行されます。

import React , { Component } from 'react';
import { Col } from "react-bootstrap";
import { connect } from 'react-redux';
import Home from "../components/Home";
import { fetchHome, asideArticle } from "../actions/index";

let createHandlers = function(dispatch) {
    let onClick = function(node, articleId) {
        dispatch(asideArticle(articleId))
    };
    return {
        onClick
    };
}

class HomeContainer extends Component {
    constructor(props) {
        super(props);
        this.handlers = createHandlers(this.props.dispatch); 
        console.log('constructor => this.props.dispatch => Result => dispatch is undefined);
    }
    componentDidMount() {
        this.props.fetchHome();
    }

    render() {
        const { homeData, article } = this.props;


       // 
        return (
            <Col>
                <Home homeData={homeData} asideArticle={(articleId) => asideArticle(articleId) } />
            </Col>
        );
    }
}

const mapStateToProps = state => ({
    homeData : state.home,
    article: state
});

function loadData(store){
    return store.dispatch(fetchHome());
}

export default {
    loadData,
    component: connect(mapStateToProps, { fetchHome, asideArticle })(HomeContainer)
}

クリックイベントを渡してthis.handlersを渡し、 articleIdを渡すにはどうすればよいですか?
そして、 nodeパラメータはfunction(node, articleId)で何を意味し、それは何をしますか?

@EhsanFahami

これはバグトラッカーであり、サポートシステムではありません。 使用法に関する質問については、Stack OverflowまたはReactifluxを使用してください。多くの人があなたを助けてくれる準備ができています。おそらく、より良い答えがより早く得られるでしょう。 ありがとう!

このページは役に立ちましたか?
0 / 5 - 0 評価