Ich entschuldige mich, wenn dies bereits geklärt wurde, aber eine Stichwortsuche in den Ausgaben hat nichts ergeben, was geholfen hat.
Wenn ich store.dispatch(someAction)
aus einer Komponentendatei aufrufen möchte, wie kann ich dann korrekt auf die Instanz store
zugreifen?
Im Moment habe ich Folgendes, was funktioniert, aber ich bin mir nicht sicher, ob es der richtige Ansatz ist:
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
}
});
Ist etwas falsch daran, das Geschäft so zu exportieren / importieren? Ich denke, ich könnte einfach die Klick-Handler als Teil der React-Komponente erstellen und this.context.store
aufrufen, aber in Wirklichkeit gibt es ungefähr ein Dutzend verschiedene Event-Handler, die an die D3-Visualisierung übergeben werden. Das ist also nicht wirklich praktisch Situation.
Unter https://github.com/rackt/react-redux finden Sie eine Hilfsmethode zum Binden des Versands an Ihre Komponenten
Insbesondere von https://redux.js.org/docs/basics/UsageWithReact.html
Jede mit connect () aufgerufene Komponente erhält eine Versandfunktion als Requisite und jeden Status, den sie benötigt, vom globalen Status.
Ist etwas falsch daran, das Geschäft so zu exportieren / importieren?
Dies funktioniert nicht, wenn Sie Ihre App auf dem Server rendern, da Sie pro Anforderung auf dem Server eine andere store
-Instanz haben möchten. Aus diesem Grund empfehlen wir diesen Ansatz in den Dokumenten nie.
Warum nicht stattdessen?
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 Sieht gut aus, danke!
@gaearon Nachdem ich es ausprobiert habe, bekomme ich undefined
für this.props.dispatch
.
Die relevanten Teile meines Codes:
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);
Nachdem ich jedoch eine andere Ausgabe gelesen hatte (https://github.com/rackt/redux/issues/239), wurde mir klar, dass ich meine Aktionen tatsächlich über connect()
an this.props
connect()
, damit ich kann Übergeben Sie einfach die erforderliche Aktion, wenn ich createHandlers()
. Vielleicht ist dies nicht der beste Ansatz, aber er funktioniert jetzt:
...
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
}
...
Nachdem ich es ausprobiert habe, werde ich für this.props.dispatch undefiniert.
Weil Sie den von mir geposteten Code nicht ausführen. In dem Code, den ich gepostet habe, hat connect
keinen zweiten Parameter erhalten. Sie übergeben dort vizActions
. Deshalb bekommst du nicht dispatch
. Wenn Sie vizActions
aus connect
entfernen, erhalten Sie es.
Beide Ansätze sind jedoch gleichwertig. Entscheiden Sie sich also für das, was Ihnen am besten gefällt.
: +1: Ok, das macht jetzt Sinn. Danke für die Hilfe!
Etwas spät zur Party, aber nur für den Fall, dass es später jemandem hilft (einschließlich mir).
Wenn ein benutzerdefiniertes mapDispatchToProps
benötigt wird (der zweite Parameter, der zum Verbinden übergeben wird), fügen Sie explizit dispatch
als einen der Schlüssel hinzu.
const mapDispatchToProps = (dispatch) => {
return {
dispatch,
// ... other custom mapped dispatch functions ...
myFunction: (myParam) => {
dispatch(State.Actions...)
},
}
}
export default connect( mapStateToProps, mapDispatchToProps )(Viz);
Hallo. Ich habe auch dieses Problem.
@gaearon , ich bin dankbar für deine Anleitung. Ich habe Ihre Lösungen verwendet, kann sie jedoch nicht verstehen und verwenden.
Ich weiß nicht, wie ich this.handlers
Wenn der Benutzer auf eine Karte klickt, sende ich diese Karten-ID an die Komponenten des Elternteils und führe die Aktion aus.
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)
}
Wie kann ich this.handlers
und articleId
nachdem ich das Klickereignis bestanden habe, um es zu übergeben?
Und was bedeutet der Parameter node
im function(node, articleId)
und was macht er?
@EhsanFahami :
Dies ist ein Bug-Tracker, kein Support-System. Bei Fragen zur Verwendung verwenden Sie bitte Stack Overflow oder Reactiflux, wo viel mehr Leute bereit sind, Ihnen zu helfen - Sie werden wahrscheinlich schneller eine bessere Antwort erhalten. Vielen Dank!
Hilfreichster Kommentar
Dies funktioniert nicht, wenn Sie Ihre App auf dem Server rendern, da Sie pro Anforderung auf dem Server eine andere
store
-Instanz haben möchten. Aus diesem Grund empfehlen wir diesen Ansatz in den Dokumenten nie.Warum nicht stattdessen?