Redux: Chamando store.dispatch () de um arquivo de componente React?

Criado em 19 out. 2015  ·  10Comentários  ·  Fonte: reduxjs/redux

Peço desculpas se isso é algo que já foi esclarecido, mas uma pesquisa por palavra-chave nos problemas não revelou nada que ajudasse.

Se eu quiser chamar store.dispatch(someAction) de um arquivo de componente, qual é a maneira correta de acessar a instância store ?

No momento, tenho o seguinte, que funciona, mas não tenho certeza se é a abordagem certa:

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
  }
});

Há algo de errado em exportar / importar a loja assim? Acho que poderia simplesmente criar os manipuladores de clique como parte do componente React e chamar this.context.store , mas na realidade há cerca de uma dúzia de manipuladores de eventos diferentes que são passados ​​para a visualização D3, então isso não é muito prático neste situação.

question

Comentários muito úteis

Há algo de errado em exportar / importar a loja assim?

Isso não funcionará se você renderizar seu aplicativo no servidor porque deseja ter uma instância store por solicitação no servidor. É por isso que nunca recomendamos essa abordagem nos documentos.

Por que não fazer isso?

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);

Todos 10 comentários

Confira https://github.com/rackt/react-redux para um método auxiliar para vincular o despacho aos seus componentes

Especificamente, em https://redux.js.org/docs/basics/UsageWithReact.html

Qualquer componente empacotado com a chamada connect () receberá uma função de despacho como um suporte e qualquer estado de que precisa do estado global.

  • Comentário atualizado com novo link para a página relevante, onde o conteúdo não existe mais

Há algo de errado em exportar / importar a loja assim?

Isso não funcionará se você renderizar seu aplicativo no servidor porque deseja ter uma instância store por solicitação no servidor. É por isso que nunca recomendamos essa abordagem nos documentos.

Por que não fazer isso?

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 Parece ótimo, obrigado!

@gaearon Na verdade, depois de experimentar, estou recebendo undefined por this.props.dispatch .

As partes relevantes do meu código:

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);

No entanto, depois de ler outro problema (https://github.com/rackt/redux/issues/239), percebi que estou vinculando minhas ações a this.props via connect() , para que eu possa apenas passe a ação necessária quando eu chamo createHandlers() . Talvez esta não seja a melhor abordagem, mas funciona agora:

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

Na verdade, depois de experimentar, estou ficando indefinido para this.props.dispatch.

Porque você não está executando o código que postei. No código que postei connect não recebeu o segundo parâmetro. Você passa vizActions lá. É por isso que você não ganha dispatch . Se você remover vizActions da chamada connect você o obterá.

Ambas as abordagens são equivalentes, então vá com o que parecer melhor para você.

: +1: Ok, isso faz sentido agora. Obrigado pela ajuda!

Meio atrasado para a festa, mas respondendo para o caso de ajudar alguém mais tarde (inclusive eu).
Se um mapDispatchToProps for necessário (o segundo parâmetro passado para conectar), adicione explicitamente dispatch como uma das chaves.

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

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

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

Oi. Eu também tenho esse problema.
@gaearon , agradeço sua orientação. Eu usei suas soluções, mas não consigo entender e usar.
Não sei como usar this.handlers Quando o usuário clica em um cartão, eu envio a identificação do cartão para os componentes do pai e executo a ação.

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

Como posso usar this.handlers e passar articleId depois de passar no evento click para passá-lo?
E o que o parâmetro node significa no function(node, articleId) e o que ele faz?

@EhsanFahami :

Este é um rastreador de bug, não um sistema de suporte. Para questões de uso, use Stack Overflow ou Reactiflux onde há muito mais pessoas prontas para ajudá-lo - você provavelmente obterá uma resposta melhor mais rápido. Obrigado!

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

ilearnio picture ilearnio  ·  3Comentários

parallelthought picture parallelthought  ·  3Comentários

jbri7357 picture jbri7357  ·  3Comentários

ms88privat picture ms88privat  ·  3Comentários

captbaritone picture captbaritone  ·  3Comentários