React: Singleton-Reaktionskomponente

Erstellt am 27. Nov. 2015  ·  5Kommentare  ·  Quelle: facebook/react

Hallo Leute!
In dieser Anwendung, die ich schreibe, gibt es eine Komponente namens "Hilfeabschnitt". Es handelt sich im Grunde genommen um eine Box, in der einige vordefinierte Texte zu der Komponente angezeigt werden, mit der der Benutzer spielt.

Ich möchte meiner Komponente "Hilfeabschnitt" mitteilen können, für welche Komponente Hilfe angezeigt werden soll. Ab sofort verwende ich Flux mit einigen Aktionen und einem Geschäft. Das ist nicht schlecht und funktioniert ganz gut, aber es ist ein ziemlich großes Setup mit 2 Dateien, die speziell für diesen Zweck definiert wurden. Es gibt auch eine Reihe anderer Probleme, die aufgetreten sind, z. B. das Versenden von Aktionen im Abschnitt "Hilfeabschnitt" aufgrund anderer Aktionen (wodurch der Fehler "Kann nicht mitten im Versand versendet werden" ausgelöst wird).

Wenn ich jedoch "Hilfeabschnitt" als Singleton definieren könnte, könnte ich nur import helpSection from './HelpSection und damit fertig sein, da ich die Instanz von "Hilfeabschnitt" bekomme. Ich muss lediglich eine Methode für helpSection verfügbar machen, die die Eigenschaften festlegt, die ich ändern und aufrufen möchte.

Ich weiß, dass es den unidirektionalen Datenfluss von React unterbricht, wenn eine Komponente eine andere Komponente ändert, aber vielleicht lohnt es sich manchmal. So wie ich das sehe, ist es eine Art Kombination aus einem Geschäft, einigen Aktionen und einer Komponente in einem Objekt. Viele Komponenten werden zur Laufzeit nur einmal instanziiert, daher ist dies in einigen Fällen möglicherweise sehr nützlich.

Ich konnte im Web keinen anderen Hinweis darauf finden als in dieser JSfiddle , die gut zu funktionieren scheint (es ist ein bisschen unklar, IMO). Ist das ein guter Weg, es zu tun?

Ich bin ein ziemlicher Neuling in JavaScript und React, daher fehlen mir möglicherweise einige offensichtliche Punkte, hoffentlich nicht.
Was denkst du darüber?
Danke fürs Lesen.

(PS Entschuldigung für Unklarheiten, Englisch ist nicht meine Muttersprache ...: smile :)

Question

Hilfreichster Kommentar

Hallo @all ,

Ich möchte dieses Gespräch wiederbeleben, indem ich einen weiteren Standpunkt hinzufüge. Wir reagieren bei 16 Es ist möglich, Komponenten mithilfe von Portalen an bestimmten Punkten des DOM zu App.jsx wie folgt gemountet ist.

App.jsx

[...]
render() {
  return (<SingletonOverlay></SingletonOverlay>)
}
[...]

Notification.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import NotificationComponent from './Notification.js';
import SingletonOverlay from '../general/Overlay.js';

export default class Notification extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      element: null
    };
  }

  componentDidMount() {
    this.setState({ element: ReactDOM.findDOMNode(SingletonOverlay) });
  }

  render() {
    return this.state.element
      ? ReactDOM.createPortal(
        <NotificationComponent>That is a notification</NotificationComponent>,
        this.state.element,
      )
      : null;
  }
}

Die andere Möglichkeit wäre, den domNode mit document.findElementById oder ähnlichen Funktionen zu finden und an ReactDOM.findDOMNode , was mich sehr unangenehm macht, da ich gezwungen bin, den "React-Cosmos" zu verlassen.

Daher würde ich gerne nach Instanzen einer bestimmten Komponente suchen können, die ich an die Funktion übergebe, anstatt die Instanz selbst für die oben genannte Funktion zu übergeben. Ich bin auch an anderen Ansätzen interessiert, wie man dieses Problem löst.

@ Jimfb Wäre dies einen Funktionsvorschlag wert?

Alle 5 Kommentare

Dies sieht eher nach einer Verwendungsfrage aus als nach einem Fehler im React-Kern. Verwendungsfragen werden auf Websites wie StackOverflow besser beantwortet, da wir versuchen, Github-Probleme zum Verfolgen von Fehlern im React-Kern zu verwenden. Aus diesem Grund werde ich dieses Problem schließen, aber Sie können die Konversation hier fortsetzen oder in StackOverflow verschieben.

In Bezug auf Ihre Frage ist meine persönliche Empfehlung, dass Sie Singletons vermeiden.
http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

Danke für die Antwort.
Gibt es bereits eine Möglichkeit, React-Komponenten als Singletons zu erstellen, die mir nicht bekannt sind? (Ich vertraue der JSfiddle erst, wenn sie von einem von euch Senioren bewertet wurde.) Wenn ja, teilen Sie es mir bitte mit, da ich in den Dokumenten nichts darüber finden konnte.

Auf der Dokumentseite "Zwischen Komponenten kommunizieren" :

Für die Kommunikation zwischen zwei Komponenten, die keine Eltern-Kind-Beziehung haben, können Sie Ihr eigenes globales Ereignissystem einrichten.
...
Das Flussmuster ist eine der möglichen Möglichkeiten, dies anzuordnen.

Wie Sie sehen können, werden Singletons nicht erwähnt. In dem von Ihnen angegebenen StackOverflow-Link haben viele Leute tatsächlich gesagt, dass die Verwendung von Singletons in einigen Fällen nützlich ist. Aus der zweiten Antwort:

Singletons lösen ein (und nur ein) Problem.
Ressourcenkonflikt.
Wenn Sie eine Ressource haben, die
(1) kann nur eine einzige Instanz haben, und
(2) Sie müssen diese einzelne Instanz verwalten.
Du brauchst einen Singleton.

Das klingt nach meinem Anwendungsfall (und einigen weiteren in der React-Welt).

Ich glaube, dass dies als Problem auf GitHub immer noch relevant ist, da es eine relevante Möglichkeit zu sein scheint, Komponenten zu verwenden, und ich denke, dass die Dokumente einen Verweis darauf enthalten sollten.

Instanzen von Reaktionskomponenten haben einen internen Status, der erforderlich ist, um zu wissen, wo sich diese Instanz in einem Baum befindet. Sie können dieselbe Instanz nicht an mehreren Stellen rendern lassen. Daher macht die Idee von Singleton-Instanzen in der React-Welt keinen Sinn.

Was in dieser Geige gezeigt wird, ist nicht wirklich das, was ich hauptsächlich wegen des Einzelinstanzarguments als Singleton bezeichnen würde - es ist eher wie ein Modul mit einem eigenen Status. Wenn eine Instanz gerendert wird, wird der eingeschlossene (aber wirklich "globale") Status verwendet. Es betrügt und speichert einen Verweis auf die gemountete Instanz in ihrem globalen Status und erzwingt ein Update für die gemountete Instanz. Jetzt hindert Sie nichts mehr daran, mehr davon zu rendern, was dazu führen würde, dass das erste nicht aktualisiert wird. Sie könnten leicht etwas Ähnliches tun und das Rendern von mehr als 1 unterstützen.

Wenn wir in unseren Dokumenten darauf verweisen, werden wir das nicht tun. Es gibt viele Muster, die mit React erreicht werden könnten, aber wir werden nicht über alle sprechen.

Danke, dass du dir die Zeit genommen hast zu antworten, James.
Erstens verstehe ich Ihre Punkte vollständig und schätze die Tatsache, dass Sie einen Blick in die JSfiddle geworfen haben. Lassen Sie mich nur eine abschließende Erklärung abgeben.

  1. Was ich als "Singleton" gemeint habe, ist eine Instanz einer React-Komponente, die in der gesamten App nur einmal gerendert wird. Das war mein Ausgangspunkt. Daher ist das von Ihnen erwähnte Problem, dass das erste nicht aktualisiert wird, wenn mehr als 1 gerendert wird, nicht so relevant.
  2. Ich weiß, dass das "Kontaminieren" des globalen Namespace verpönt ist, aber wie jeder Codierungsansatz hat er seinen Platz und seine Verwendung. Die Verwendung von Flux für diese Art von Dingen ist aus verschiedenen Gründen problematisch (ich hatte ungefähr einen guten Tag damit zu kämpfen), und selbst jetzt ist die Lösung, die ich gefunden habe, nicht so gut (Die Komponente "wählt" zwischen den Requisiten oder den Geschäft). Die Verwendung eines Singletons, wie ich es beschrieben habe, kann dies viel einfacher machen . Ich denke, die Vorteile überwiegen die Nachteile.
  3. Sie wissen, in Bezug auf die Dokumente. Ich benutze React seit ungefähr 2 Monaten und es ist kein Geheimnis, dass die Dokumente an einigen Stellen stark fehlen. Für mich war es schwierig und verwirrend, React zu lernen.
    Die Dokumente enthalten derzeit 3 Sätze zur Kommunikation zwischen Komponenten, die keine "Familien" -Beziehung haben. Ich verstehe, dass die Vielfalt der für diese Art von Mustern verfügbaren Muster für Sie offensichtlich ist, aber ich bin bisher nur auf Flux gestoßen.
    Anfänger verlassen sich stark auf die Dokumente, und vielleicht ist es genau das, was Sie tun sollten, wenn Sie die möglichen Muster auflisten, die zur Lösung aller möglichen Probleme verfügbar sind. Wir können Muster selbst gründlich lernen, und es ist schwierig zu lernen, welches Werkzeug für die Aufgabe geeignet ist.

Ich möchte die Dinge, die mir schwer fielen, leichter machen. Ich denke, es wird eine Frage von ein paar Zeilen sein und könnte Anfängern in Zukunft helfen.

Am Ende schreibe ich immer große Kommentare. Danke, dass du bei mir geblieben bist und gelesen hast. :Lächeln:

Hallo @all ,

Ich möchte dieses Gespräch wiederbeleben, indem ich einen weiteren Standpunkt hinzufüge. Wir reagieren bei 16 Es ist möglich, Komponenten mithilfe von Portalen an bestimmten Punkten des DOM zu App.jsx wie folgt gemountet ist.

App.jsx

[...]
render() {
  return (<SingletonOverlay></SingletonOverlay>)
}
[...]

Notification.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import NotificationComponent from './Notification.js';
import SingletonOverlay from '../general/Overlay.js';

export default class Notification extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      element: null
    };
  }

  componentDidMount() {
    this.setState({ element: ReactDOM.findDOMNode(SingletonOverlay) });
  }

  render() {
    return this.state.element
      ? ReactDOM.createPortal(
        <NotificationComponent>That is a notification</NotificationComponent>,
        this.state.element,
      )
      : null;
  }
}

Die andere Möglichkeit wäre, den domNode mit document.findElementById oder ähnlichen Funktionen zu finden und an ReactDOM.findDOMNode , was mich sehr unangenehm macht, da ich gezwungen bin, den "React-Cosmos" zu verlassen.

Daher würde ich gerne nach Instanzen einer bestimmten Komponente suchen können, die ich an die Funktion übergebe, anstatt die Instanz selbst für die oben genannte Funktion zu übergeben. Ich bin auch an anderen Ansätzen interessiert, wie man dieses Problem löst.

@ Jimfb Wäre dies einen Funktionsvorschlag wert?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen