Redux: Store.dispatch () aus einer React-Komponentendatei aufrufen?

Erstellt am 19. Okt. 2015  ·  10Kommentare  ·  Quelle: reduxjs/redux

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.

question

Hilfreichster Kommentar

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

Alle 10 Kommentare

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.

  • Der Kommentar wurde mit einem neuen Link zu einer relevanten Seite aktualisiert, auf der der Inhalt nicht mehr vorhanden ist

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!

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

vslinko picture vslinko  ·  3Kommentare

captbaritone picture captbaritone  ·  3Kommentare

ramakay picture ramakay  ·  3Kommentare

ilearnio picture ilearnio  ·  3Kommentare

cloudfroster picture cloudfroster  ·  3Kommentare