Je m'excuse si c'est quelque chose qui a déjà été clarifié, mais une recherche par mot-clé dans les problèmes n'a rien trouvé qui ait aidé.
Si je veux appeler store.dispatch(someAction)
partir d'un fichier de composant, quelle est la manière correcte d'accéder à l'instance store
?
Pour le moment, j'ai ce qui suit, qui fonctionne, mais je ne suis pas sûr que ce soit la bonne approche:
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
}
});
Y a-t-il quelque chose de mal à exporter / importer le magasin comme celui-ci? Je pense que je pourrais simplement créer les gestionnaires de clics dans le cadre du composant React et appeler this.context.store
, mais en réalité, il y a environ une douzaine de gestionnaires d'événements différents qui sont passés à la visualisation D3, donc ce n'est pas vraiment pratique dans ce domaine. situation.
Consultez https://github.com/rackt/react-redux pour une méthode d'aide pour lier la distribution à vos composants
Plus précisément, à partir de https://redux.js.org/docs/basics/UsageWithReact.html
Tout composant encapsulé avec un appel connect () recevra une fonction de répartition en tant que prop, et tout état dont il a besoin de l'état global.
Y a-t-il quelque chose de mal à exporter / importer le magasin comme celui-ci?
Cela ne fonctionnera pas si vous affichez votre application sur le serveur, car vous souhaitez avoir store
instance
Pourquoi ne pas faire cela à la place?
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 a l'air super, merci!
@gaearon En fait, après l'avoir essayé, je reçois undefined
pour this.props.dispatch
.
Les parties pertinentes de mon code:
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);
Cependant, après avoir lu un autre numéro (https://github.com/rackt/redux/issues/239), j'ai réalisé que je liais réellement mes actions à this.props
via connect()
, donc je peux passez simplement l'action nécessaire lorsque j'appelle createHandlers()
. Ce n'est peut-être pas la meilleure approche, mais cela fonctionne maintenant:
...
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 fait, après l'avoir essayé, je ne suis plus défini pour this.props.dispatch.
Parce que vous n'exécutez pas le code que j'ai publié. Dans le code, j'ai posté connect
je n'ai pas reçu de deuxième paramètre. Vous y passez vizActions
. C'est pourquoi vous n'obtenez pas dispatch
. Si vous supprimez vizActions
de connect
call, vous l'obtiendrez.
Les deux approches sont cependant équivalentes, alors choisissez ce qui vous convient le mieux.
: +1: Ok, ça a du sens maintenant. Merci pour l'aide!
Un peu tard à la fête, mais répondre juste au cas où cela aiderait quelqu'un plus tard (y compris moi-même).
Si un mapDispatchToProps
est nécessaire (le deuxième paramètre passé pour se connecter), ajoutez explicitement dispatch
comme l'une des clés.
const mapDispatchToProps = (dispatch) => {
return {
dispatch,
// ... other custom mapped dispatch functions ...
myFunction: (myParam) => {
dispatch(State.Actions...)
},
}
}
export default connect( mapStateToProps, mapDispatchToProps )(Viz);
Salut. J'ai aussi ce problème.
@gaearon , je suis reconnaissant de vos conseils. J'ai utilisé vos solutions, mais je ne peux pas les comprendre et les utiliser.
Je ne sais pas comment utiliser this.handlers
Lorsque l'utilisateur clique sur une carte, j'envoie cet identifiant de carte aux composants du parent et lance l'action.
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)
}
Comment puis-je utiliser this.handlers
et passer le articleId
après avoir passé l'événement click pour le transmettre?
Et que signifie le paramètre node
dans le function(node, articleId)
et que fait-il?
@EhsanFahami :
Ceci est un bug tracker, pas un système de support. Pour les questions d'utilisation, veuillez utiliser Stack Overflow ou Reactiflux où il y a beaucoup plus de personnes prêtes à vous aider - vous obtiendrez probablement une meilleure réponse plus rapidement. Merci!
Commentaire le plus utile
Cela ne fonctionnera pas si vous affichez votre application sur le serveur, car vous souhaitez avoir
store
instancePourquoi ne pas faire cela à la place?