Redux: ¿Llamar a store.dispatch () desde un archivo de componente de React?

Creado en 19 oct. 2015  ·  10Comentarios  ·  Fuente: reduxjs/redux

Me disculpo si esto es algo que ya se ha aclarado, pero una búsqueda de palabras clave en los problemas no arrojó nada que ayudara.

Si quiero llamar a store.dispatch(someAction) desde un archivo de componente, ¿cuál es la forma correcta de acceder a la instancia store ?

En este momento tengo lo siguiente, que funciona, pero no estoy seguro de que sea el enfoque correcto:

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

¿Hay algo de malo en exportar / importar la tienda de esta manera? Creo que podría crear los controladores de clic como parte del componente React y llamar a this.context.store , pero en realidad hay alrededor de una docena de controladores de eventos diferentes que se pasan a la visualización D3, por lo que eso no es realmente práctico en esto. situación.

question

Comentario más útil

¿Hay algo de malo en exportar / importar la tienda de esta manera?

Esto no funcionará si procesa su aplicación en el servidor porque desea tener una instancia store por solicitud en el servidor. Es por eso que nunca recomendamos este enfoque en los documentos.

¿Por qué no hacer esto en su lugar?

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 comentarios

Consulte https://github.com/rackt/react-redux para obtener un método auxiliar para vincular el envío a sus componentes

Específicamente, de https://redux.js.org/docs/basics/UsageWithReact.html

Cualquier componente envuelto con la llamada connect () recibirá una función de envío como accesorio y cualquier estado que necesite del estado global.

  • Comentario actualizado con un nuevo enlace a la página relevante, donde el contenido ya no existe

¿Hay algo de malo en exportar / importar la tienda de esta manera?

Esto no funcionará si procesa su aplicación en el servidor porque desea tener una instancia store por solicitud en el servidor. Es por eso que nunca recomendamos este enfoque en los documentos.

¿Por qué no hacer esto en su lugar?

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 Se ve genial, ¡gracias!

@gaearon En realidad, después de probarlo, undefined por this.props.dispatch .

Las partes relevantes de mi 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);

Sin embargo, después de leer otro número (https://github.com/rackt/redux/issues/239) me di cuenta de que en realidad estoy vinculando mis acciones a this.props través de connect() , así que puedo simplemente pase la acción necesaria cuando llamo createHandlers() . Quizás este no sea el mejor enfoque, pero funciona ahora:

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

En realidad, después de probarlo, no estoy definido para this.props.dispatch.

Porque no está ejecutando el código que publiqué. En el código que publiqué connect no recibió el segundo parámetro. Pasas vizActions allí. Por eso no obtienes dispatch . Si elimina vizActions de connect call, lo obtendrá.

Sin embargo, ambos enfoques son equivalentes, así que elija lo que mejor le parezca.

: +1: Ok, eso tiene sentido ahora. ¡Gracias por la ayuda!

Un poco tarde para la fiesta, pero respondiendo por si acaso ayuda a alguien más tarde (incluyéndome a mí).
Si se necesita un mapDispatchToProps (el segundo parámetro pasado para conectarse), agregue explícitamente dispatch como una de las claves.

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

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

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

Hola. También tengo este problema.
@gaearon , estoy agradecido por tu orientación. He usado sus soluciones, pero no puedo entenderlas ni usarlas.
No sé cómo usar this.handlers Cuando el usuario hace clic en una tarjeta, envío esa identificación de tarjeta a los componentes de los padres y ejecuto la acción.

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

¿Cómo puedo usar this.handlers y pasar el articleId después de pasar el evento de clic para pasarlo?
¿Y qué significa el parámetro node en function(node, articleId) y qué hace?

@EhsanFahami :

Este es un rastreador de errores, no un sistema de soporte. Para preguntas de uso, use Stack Overflow o Reactiflux donde hay muchas más personas listas para ayudarlo; probablemente obtendrá una mejor respuesta más rápido. ¡Gracias!

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

timdorr picture timdorr  ·  3Comentarios

caojinli picture caojinli  ·  3Comentarios

cloudfroster picture cloudfroster  ·  3Comentarios

mickeyreiss-visor picture mickeyreiss-visor  ·  3Comentarios

ramakay picture ramakay  ·  3Comentarios