React: Composant Singleton React

Créé le 27 nov. 2015  ·  5Commentaires  ·  Source: facebook/react

Salut les gars!
Donc, dans cette application que j'écris, il y a un composant appelé "section d'aide". Il s'agit essentiellement d'une boîte qui montre des textes prédéfinis sur le composant avec lequel l'utilisateur joue.

Je veux pouvoir indiquer à mon composant "section d'aide" le composant pour lequel afficher l'aide. Pour le moment, j'utilise Flux avec quelques actions et un magasin. Ce n'est pas trop mal et fonctionne assez bien, mais c'est une configuration assez volumineuse, avec 2 fichiers définis spécifiquement pour cette cause. Il y a également un certain nombre d'autres problèmes que j'ai rencontrés, tels que l'envoi d'actions de "section d'aide" en raison d'autres actions (ce qui déclenche une erreur "Ne peut pas envoyer au milieu d'une distribution").

Cependant, si je pouvais définir "help section" comme un singleton , je pourrais juste import helpSection from './HelpSection et en finir avec, puisque j'obtiendrai l' instance de "help section". Tout ce que j'ai à faire est d'exposer une méthode sur helpSection qui définit les propriétés que je veux changer et l'appelle.

Je sais que cela rompt le flux de données unidirectionnel de React, avec un composant en changeant un autre composant, mais cela en vaut peut-être la peine parfois. À mon avis, c'est une sorte de combinaison d'un magasin, de certaines actions et d'un composant en un seul objet. Un grand nombre de composants ne seront instanciés qu'une seule fois au moment de l'exécution, alors peut-être que cela sera très utile dans certains cas.

Je n'ai trouvé aucune référence à cela sur le Web à part dans ce JSfiddle , qui semble fonctionner correctement (c'est un peu incertain à l'OMI). Est-ce une bonne façon de le faire?

Je suis assez novice en JavaScript et React, donc il me manque peut-être des points évidents, j'espère que non.
Que penses-tu de cela?
Merci d'avoir lu.

(PS Désolé pour toute ambiguïté, l'anglais n'est pas ma langue maternelle ...: sourire :)

Question

Commentaire le plus utile

Bonjour @ tous ,

J'aimerais relancer cette conversation en ajoutant un autre point de vue. Wir react @ 16, il est possible de monter des composants dans certains points du DOM en utilisant des portails . Pour ce cas d'utilisation, je construis différents composants tels que des modaux ou des notifications qui devraient être rendus dans un certain autre composant qui est monté dans mon App.jsx comme ceci.

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

L'autre option serait de trouver le domNode avec document.findElementById ou des fonctions similaires et de les passer à ReactDOM.findDOMNode , ce qui me rend très mal à l'aise car je suis obligé de quitter le "React-Cosmos".

Par conséquent, j'aimerais pouvoir rechercher des instances d'un certain composant que je passe à la fonction, au lieu de passer l'instance elle-même, pour la fonctionnalité mentionnée ci-dessus. Im également intéressé par d'autres approches sur la façon de résoudre ce problème.

@jimfb vaut-il une proposition de fonctionnalité?

Tous les 5 commentaires

Cela ressemble à une question d'utilisation, plutôt qu'à un bogue dans le cœur de React. Les questions d'utilisation sont mieux répondues sur des sites comme StackOverflow, car nous essayons d'utiliser les problèmes github pour suivre les bogues dans le cœur de React. Pour cette raison, je vais clore ce problème, mais n'hésitez pas à poursuivre la conversation ici ou à la déplacer vers StackOverflow.

En ce qui concerne votre question, ma recommandation personnelle est que vous évitiez les singletons.
http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

Merci pour la réponse.
Existe-t-il déjà un moyen de créer des composants React en tant que singletons dont je ne suis pas au courant? (Je ne fais pas confiance au JSfiddle jusqu'à ce qu'il soit évalué par l'un de vous seniors). Si tel est le cas, partagez-le avec moi, car je n'ai rien trouvé à ce sujet dans la documentation.

Depuis la page de documentation "Communiquer entre les composants" :

Pour la communication entre deux composants qui n'ont pas de relation parent-enfant, vous pouvez configurer votre propre système d'événements global.
...
Le modèle de flux est l'un des moyens possibles d'organiser cela.

Comme vous pouvez le voir, les singletons ne sont pas mentionnés. Dans le lien StackOverflow que vous avez donné, beaucoup de gens ont dit que l'utilisation de singletons était utile dans certains cas. De la deuxième réponse:

Les singletons résolvent un (et un seul) problème.
Conflit de ressources.
Si vous avez des ressources
(1) ne peut avoir qu'une seule instance, et
(2) vous devez gérer cette seule instance,
vous avez besoin d'un singleton.

Cela ressemble à mon cas d'utilisation (et à bien d'autres dans le monde React).

Je pense que cela reste pertinent en tant que problème sur GitHub car cela semble être un moyen pertinent d'utiliser les composants, et je pense que la documentation devrait en contenir une référence.

Les instances de composant React ont un état interne qui est nécessaire pour savoir où se trouve dans une arborescence cette instance. Vous ne pouvez pas afficher la même instance à plusieurs endroits. Par conséquent, l'idée d'instances singleton n'a pas de sens dans le monde React.

Ce qui est montré dans ce violon n'est pas vraiment ce que j'appellerais un singleton principalement à cause de l'argument d'instance unique - c'est plutôt un module avec son propre état. Ensuite, lorsqu'une instance est rendue, elle utilise l'état inclus (mais vraiment "global"). Il triche et stocke une référence à l'instance montée dans son état global et force une mise à jour sur l'instance montée. Maintenant, rien ne vous empêche d'en rendre davantage, ce qui entraînerait la non mise à jour du premier. Vous pouvez facilement faire quelque chose de similaire et prendre en charge le rendu de plus de 1.

Quant à nous qui faisons référence à cela dans nos documents, nous ne le ferons pas. Il existe de nombreux modèles qui pourraient être atteints avec React, mais nous n'allons pas en parler tous.

Merci d'avoir pris le temps de répondre, James.
Premièrement, je comprends parfaitement vos points et apprécie le fait que vous ayez jeté un coup d'œil sur JSfiddle. Permettez-moi de faire une dernière déclaration.

  1. Ce que je voulais dire par "singleton" est une instance d'un composant React qui ne rend qu'une seule fois dans l'application. C'était mon point de départ. Par conséquent, le problème que vous avez mentionné à propos du premier ne pas être mis à jour si le rendu supérieur à 1 n'est pas si pertinent.
  2. Je sais que «contaminer» l'espace de noms global est mal vu, mais comme toute approche de codage, il a sa place et ses usages. Utiliser Flux pour ce genre de chose est problématique pour diverses raisons (j'ai eu du mal avec ça pendant une bonne journée ou deux) et même maintenant, la solution que j'ai trouvée n'est pas si bonne (le composant "choisit" entre les accessoires ou le boutique). Utiliser un singleton comme je l'ai décrit peut rendre cela beaucoup plus facile . Je pense que les avantages l'emportent sur les inconvénients.
  3. Vous savez, en ce qui concerne les documents. J'utilise React depuis environ 2 mois et ce n'est un secret pour personne que la documentation manque gravement à certains moments. Pour moi, apprendre à utiliser React était difficile et déroutant.
    La documentation contient actuellement 3 phrases sur la communication entre les composants qui n'ont pas de relation «familiale». Je comprends que la variété des modèles disponibles pour ce genre de chose est évidente pour vous, mais je n'ai rencontré Flux que jusqu'à présent.
    Les débutants comptent beaucoup sur les documents, et peut-être que la liste des modèles possibles disponibles pour résoudre toutes sortes de problèmes est la chose exacte que vous devriez faire. Nous pouvons apprendre des modèles en profondeur par nous-mêmes, apprendre quel outil est le bon pour la tâche est la partie la plus difficile.

Je veux faciliter les choses qui étaient difficiles pour moi. Je pense que ce sera une question de quelques lignes et pourrait aider les débutants à l'avenir.

Je finis toujours par écrire d'énormes commentaires. Merci d'être resté avec moi et d'avoir lu. :sourire:

Bonjour @ tous ,

J'aimerais relancer cette conversation en ajoutant un autre point de vue. Wir react @ 16, il est possible de monter des composants dans certains points du DOM en utilisant des portails . Pour ce cas d'utilisation, je construis différents composants tels que des modaux ou des notifications qui devraient être rendus dans un certain autre composant qui est monté dans mon App.jsx comme ceci.

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

L'autre option serait de trouver le domNode avec document.findElementById ou des fonctions similaires et de les passer à ReactDOM.findDOMNode , ce qui me rend très mal à l'aise car je suis obligé de quitter le "React-Cosmos".

Par conséquent, j'aimerais pouvoir rechercher des instances d'un certain composant que je passe à la fonction, au lieu de passer l'instance elle-même, pour la fonctionnalité mentionnée ci-dessus. Im également intéressé par d'autres approches sur la façon de résoudre ce problème.

@jimfb vaut-il une proposition de fonctionnalité?

Cette page vous a été utile?
0 / 5 - 0 notes