Redux: Вызов store.dispatch () из файла компонента React?

Созданный на 19 окт. 2015  ·  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, так что это не совсем практично в данном случае. ситуация.

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 На самом деле, попробовав, я получаю undefined за this.props.dispatch .

Соответствующие части моего кода:

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
  }
...

На самом деле, попробовав, я получаю undefined для this.props.dispatch.

Потому что вы не используете опубликованный мной код. В коде, который я написал, connect не получил второй параметр. Здесь вы передаете vizActions . Вот почему вы не получаете dispatch . Если вы удалите vizActions из вызова connect вы получите его.

Оба подхода эквивалентны, поэтому выбирайте то, что вам лучше всего подходит.

: +1: Хорошо, теперь это имеет смысл. Спасибо за помощь!

Типа поздно на вечеринку, но отвечая на всякий случай, это поможет кому-то позже (включая меня).
Если требуется пользовательский mapDispatchToProps (второй параметр передается для подключения), явно добавьте 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 Когда пользователь нажимает на карту, я отправляю этот идентификатор карты родительским компонентам и запускаю действие.

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 после передачи события click, чтобы передать его?
А что означает параметр node в function(node, articleId) и что он делает?

@EhsanFahami :

Это баг-трекер, а не система поддержки. По вопросам использования используйте Stack Overflow или Reactiflux, где гораздо больше людей готовы помочь вам - вы, вероятно, быстрее получите лучший ответ. Благодаря!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги

Смежные вопросы

benoneal picture benoneal  ·  3Комментарии

olalonde picture olalonde  ·  3Комментарии

captbaritone picture captbaritone  ·  3Комментарии

cloudfroster picture cloudfroster  ·  3Комментарии

CellOcean picture CellOcean  ·  3Комментарии