React: Componente de reacción Singleton

Creado en 27 nov. 2015  ·  5Comentarios  ·  Fuente: facebook/react

¡Hola chicos!
Entonces, en esta aplicación que estoy escribiendo, hay un componente llamado "sección de ayuda". Es básicamente un cuadro que muestra algunos textos predefinidos sobre el componente con el que está jugando el usuario.

Quiero poder decirle a mi componente "sección de ayuda" para qué componente mostrar ayuda. A partir de ahora, estoy usando Flux con algunas acciones y una tienda. Esto no es tan malo y funciona bastante bien, sin embargo, es una configuración bastante grande, con 2 archivos definidos específicamente para esta causa. También hay una serie de otros problemas que he experimentado, como el envío de acciones de la "sección de ayuda" debido a otras acciones (lo que genera un error "No se puede enviar en medio de un envío").

Sin embargo, si pudiera definir "sección de ayuda" como un singleton , podría simplemente import helpSection from './HelpSection y terminar, ya que obtendré la instancia de "sección de ayuda". Todo lo que tengo que hacer es exponer un método en helpSection que establece las propiedades que quiero cambiar y llamarlo.

Sé que rompe el flujo de datos unidireccional de React, con un componente cambiando a otro componente, pero quizás valga la pena a veces. De la forma en que lo pienso, es una especie de combinación de una tienda, algunas acciones y un componente en un objeto. Una gran cantidad de componentes solo se instanciarán una vez en tiempo de ejecución, por lo que tal vez sea bastante útil en algunos casos.

No pude encontrar ninguna referencia a esto en la web más que en este JSfiddle , que parece funcionar bien (no está claro en mi opinión). ¿Es esta una buena forma de hacerlo?

Soy bastante novato en JavaScript y React, por lo que es posible que me esté perdiendo algunos puntos obvios, ojalá no.
¿Qué piensas sobre esto?
Gracias por leer.

(PD: Perdón por cualquier ambigüedad, el inglés no es mi lengua materna ...: sonríe :)

Question

Comentario más útil

Hola @todos ,

Me gustaría revivir esta conversación agregando otro punto de vista. Wir react @ 16 es posible montar componentes en ciertos puntos del DOM usando Portals . Para este caso de uso, estoy construyendo diferentes componentes como modales o notificaciones que deberían ser procesados ​​en otro componente específico que se monta en mi App.jsx como este.

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

La otra opción sería buscar el domNode con document.findElementById o funciones similares y pasarlas a ReactDOM.findDOMNode , lo que me hace sentir muy incómodo ya que me veo obligado a dejar el "React-Cosmos".

Por lo tanto, me encantaría poder buscar Instancias de un determinado Componente que paso a la función, en lugar de pasar la instancia en sí, para la característica mencionada anteriormente. También estoy interesado en otros enfoques sobre cómo resolver este problema.

@jimfb, ¿valdría la pena una propuesta de función?

Todos 5 comentarios

Esto parece una pregunta de uso, en lugar de un error en el núcleo de React. Las preguntas de uso se responden mejor en sitios como StackOverflow, ya que intentamos usar problemas de github para rastrear errores en el núcleo de React. Por esta razón, voy a cerrar este problema, pero siéntase libre de continuar la conversación aquí o moverla a StackOverflow.

Con respecto a su pregunta, mi recomendación personal es que evite los singletons.
http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

Gracias por la respuesta.
¿Existe ya una forma de crear componentes de React como singleton que no conozca? (No confío en JSfiddle hasta que sea evaluado por uno de ustedes, senior). Si lo hay, compártelo conmigo, ya que no pude encontrar nada al respecto en los documentos.

Desde la página del documento "Comunicación entre componentes" :

Para la comunicación entre dos componentes que no tienen una relación padre-hijo, puede configurar su propio sistema de eventos global.
...
El patrón de flujo es una de las posibles formas de arreglar esto.

Como puede ver, los singletons no se mencionan. En el enlace StackOverflow que proporcionó, mucha gente dijo que usar singletons es útil en algunos casos. De la segunda respuesta:

Los singleton resuelven un problema (y solo uno).
Contención de recursos.
Si tienes algún recurso que
(1) solo puede tener una única instancia, y
(2) necesita administrar esa única instancia,
necesitas un singleton.

Este suena como mi caso de uso (y algunos más en el mundo React).

Creo que esto sigue siendo relevante como problema en GitHub, ya que parece una forma relevante de usar componentes, y creo que los documentos deberían contener una referencia al mismo.

Las instancias de componentes de React tienen un estado interno que se necesita para saber en qué parte de un árbol se encuentra esa instancia. No se puede renderizar la misma instancia en varios lugares. Por lo tanto, la idea de instancias singleton no tiene sentido en el mundo React.

Lo que se muestra en ese violín no es realmente lo que yo llamaría un singleton principalmente debido al argumento de instancia única; es más como un módulo con su propio estado. Luego, cuando se renderiza una instancia, usa el estado adjunto (pero realmente "global"). Está haciendo trampa y almacenando una referencia a la instancia montada en su estado global y forzando una actualización en la instancia montada. Ahora no hay nada que realmente le impida renderizar más de estos, lo que resultaría en que el primero no se actualice. Fácilmente podría hacer algo similar y admitir la renderización de más de 1.

En cuanto a que hagamos una referencia a esto en nuestros documentos, no lo haremos. Hay muchos patrones que se pueden lograr con React, pero no vamos a hablar de todos.

Gracias por tomarte el tiempo de responder, James.
En primer lugar, comprendo completamente sus puntos y aprecio el hecho de que haya echado un vistazo al JSfiddle. Permítanme hacer una declaración final.

  1. Lo que quise decir como "singleton" es una instancia de un componente React que se procesa solo una vez en toda la aplicación. Ese fue mi punto de partida. Por lo tanto, el problema que mencionó acerca de que el primero no se actualiza si renderizar más de 1 no es tan relevante.
  2. Sé que "contaminar" el espacio de nombres global está mal visto, pero como cualquier enfoque de codificación, tiene su lugar y sus usos. Usar Flux para este tipo de cosas es problemático por una variedad de razones (luché con él durante un buen día más o menos) e incluso ahora la solución que se me ocurrió no es tan buena (el componente "elige" entre los accesorios o el Tienda). Usar un singleton de la forma que describí puede hacer esto mucho más fácil . Creo que los beneficios superan a los contras.
  3. Ya sabes, con respecto a los documentos. He estado usando React durante aproximadamente 2 meses y no es ningún secreto que los documentos carecen gravemente en algunos puntos. Para mí, aprender a usar React fue difícil y confuso.
    Los documentos contienen actualmente 3 oraciones sobre la comunicación entre componentes que no tienen una relación "familiar". Entiendo que la variedad de patrones disponibles para este tipo de cosas es obvia para usted, pero hasta ahora solo me he encontrado con Flux.
    Los principiantes dependen en gran medida de los documentos, y tal vez enumerar los posibles patrones disponibles para resolver todo tipo de problemas es exactamente lo que debe hacer. Podemos aprender patrones en profundidad por nosotros mismos, aprender qué herramienta es adecuada para la tarea es la parte difícil.

Quiero facilitar las cosas que me resultaron difíciles. Creo que será cuestión de unas pocas líneas y podría ayudar a los principiantes en el futuro.

Siempre termino escribiendo comentarios enormes ... Gracias por seguirme y leer. :sonreír:

Hola @todos ,

Me gustaría revivir esta conversación agregando otro punto de vista. Wir react @ 16 es posible montar componentes en ciertos puntos del DOM usando Portals . Para este caso de uso, estoy construyendo diferentes componentes como modales o notificaciones que deberían ser procesados ​​en otro componente específico que se monta en mi App.jsx como este.

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

La otra opción sería buscar el domNode con document.findElementById o funciones similares y pasarlas a ReactDOM.findDOMNode , lo que me hace sentir muy incómodo ya que me veo obligado a dejar el "React-Cosmos".

Por lo tanto, me encantaría poder buscar Instancias de un determinado Componente que paso a la función, en lugar de pasar la instancia en sí, para la característica mencionada anteriormente. También estoy interesado en otros enfoques sobre cómo resolver este problema.

@jimfb, ¿valdría la pena una propuesta de función?

¿Fue útil esta página
0 / 5 - 0 calificaciones