React: Componente Singleton React

Criado em 27 nov. 2015  ·  5Comentários  ·  Fonte: facebook/react

Ei pessoal!
Portanto, neste aplicativo que estou escrevendo, há um componente chamado "seção de ajuda". É basicamente uma caixa que mostra alguns textos pré-definidos sobre o componente que o usuário está mexendo.

Eu quero ser capaz de dizer ao meu componente de "seção de ajuda" para qual componente mostrar ajuda. No momento, estou usando o Flux com algumas ações e uma loja. Isso não é tão ruim e funciona muito bem, no entanto, é uma configuração bastante grande, com 2 arquivos definidos especificamente para essa causa. Há também vários outros problemas que eu experimentei, como ações da "seção de ajuda" despachadas por causa de outras ações (que geram um erro "Não é possível despachar no meio de um despacho").

No entanto, se eu pudesse definir "seção de ajuda" como um singleton , poderia apenas import helpSection from './HelpSection e encerrar, já que obterei a instância de "seção de ajuda". Tudo o que tenho a fazer é expor um método em helpSection que define as propriedades que desejo alterar e chamá-lo.

Eu sei que isso quebra o fluxo de dados unidirecional do React, com um componente alterando outro componente, mas talvez valha a pena às vezes. A maneira como penso sobre isso é uma espécie de combinação de uma loja, algumas ações e um componente em um objeto. Muitos componentes só serão instanciados uma vez em tempo de execução, então talvez seja bastante útil em alguns casos.

Não consegui encontrar nenhuma referência a isso na web a não ser neste JSfiddle , que parece funcionar bem (é um pouco confuso, IMO). Esta é uma boa maneira de fazer isso?

Sou um novato em JavaScript e React, então posso estar perdendo alguns pontos óbvios, espero que não.
O que você pensa sobre isso?
Obrigado pela leitura.

(PS, desculpe qualquer ambiguidade, Inglês não é minha língua nativa ...: sorria :)

Question

Comentários muito úteis

Olá @todos ,

Eu gostaria de reviver essa conversa adicionando outro ponto de vista. Wir react @ 16 é possível montar componentes em certos pontos do DOM usando Portals . Para este caso de uso, estou construindo diferentes componentes, como modais ou notificações, que devem ser renderizados em um determinado outro componente que é montado em meu App.jsx assim.

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

A outra opção seria encontrar o domNode com document.findElementById ou funções semelhantes e passá-los para ReactDOM.findDOMNode , o que me faz sentir muito desagradável, pois sou forçado a deixar o "React-Cosmos".

Portanto, eu adoraria ser capaz de pesquisar instâncias de um determinado componente que eu passo para a função, em vez de passar a própria instância, para o recurso mencionado acima. Também estou interessado em outras abordagens sobre como resolver esse problema.

@jimfb valeria a pena uma proposta de recurso?

Todos 5 comentários

Isso parece uma questão de uso, em vez de um bug no núcleo do React. As perguntas de uso são melhor respondidas em sites como StackOverflow, pois tentamos usar problemas do github para rastrear bugs no núcleo do React. Por esse motivo, encerrarei este problema, mas fique à vontade para continuar a conversa aqui ou movê-lo para StackOverflow.

Com relação à sua pergunta, minha recomendação pessoal é que você evite solteiros.
http://stackoverflow.com/questions/137975/what-is-so-bad-about-singletons

Obrigado pela resposta.
Já existe uma maneira de criar componentes React como singletons que eu não conheço? (Eu não confio no JSfiddle até que seja avaliado por um de vocês, idosos). Se houver, compartilhe comigo, pois não consegui encontrar nada sobre ele nos documentos.

Na página do documento "Comunicar-se entre os componentes" :

Para a comunicação entre dois componentes que não têm um relacionamento pai-filho, você pode configurar seu próprio sistema de eventos global.
...
O padrão de fluxo é uma das maneiras possíveis de organizar isso.

Como você pode ver, singletons não são mencionados. No link StackOverflow que você forneceu, muitas pessoas disseram que usar singletons é útil em alguns casos. Da segunda resposta:

Singletons resolvem um (e apenas um) problema.
Contenção de recursos.
Se você tem algum recurso que
(1) pode ter apenas uma única instância, e
(2) você precisa gerenciar essa única instância,
você precisa de um singleton.

Isso soa como meu caso de uso (e alguns mais no mundo React).

Acredito que isso ainda seja relevante como um problema no GitHub, pois parece uma forma relevante de usar componentes, e acho que os documentos devem conter uma referência a isso.

As instâncias do componente React têm um estado interno que é necessário para saber onde essa instância está dentro de uma árvore. Você não pode ter a mesma instância renderizada em vários lugares. Portanto, a ideia de instâncias singleton não faz sentido no mundo React.

O que é mostrado nesse violino não é realmente o que eu chamaria de singleton principalmente por causa do argumento de instância única - é mais como um módulo com seu próprio estado. Então, quando uma instância é renderizada, ela usa o estado fechado (mas na verdade "global"). Ele está trapaceando e armazenando uma referência à instância montada em seu estado global e forçando uma atualização na instância montada. Agora, não há nada realmente impedindo você de renderizar mais desses, o que resultaria na não atualização do primeiro. Você poderia facilmente fazer algo semelhante e suportar a renderização de mais de 1.

Quanto a fazermos uma referência a isso em nossos documentos, não faremos isso. Existem muitos padrões que podem ser alcançados com o React, mas não vamos falar sobre todos eles.

Obrigado por responder, James.
Em primeiro lugar, eu entendo completamente seus pontos e aprecio o fato de que você deu uma olhada no JSfiddle. Deixe-me fazer uma declaração final.

  1. O que eu quis dizer como "singleton" é uma instância de um componente React que é renderizado apenas uma vez em todo o aplicativo. Esse foi o meu ponto de partida. Portanto, o problema que você mencionou sobre o primeiro não ser atualizado se renderizar mais de 1 não é tão relevante.
  2. Eu sei que "contaminar" o namespace global é desaprovado, mas como qualquer abordagem de codificação, tem seu lugar e seus usos. Usar o Flux para esse tipo de coisa é problemático por uma variedade de razões (eu lutei com isso por um bom dia ou mais) e mesmo agora a solução que eu encontrei não é tão boa (o componente "escolhe" entre os adereços ou o loja). Usar um singleton da maneira que descrevi pode tornar isso muito mais fácil . Acho que os benefícios superam os contras.
  3. Você sabe, no que diz respeito aos documentos. Estou usando o React há cerca de 2 meses e não é nenhum segredo que os documentos estão faltando muito em alguns pontos. Para mim, aprender a usar o React foi difícil e confuso.
    Os documentos atualmente contêm 3 frases sobre a comunicação entre componentes que não têm uma relação de "família". Eu entendo que a variedade de padrões disponíveis para esse tipo de coisa é óbvia para você, mas só encontrei o Flux até agora.
    Os iniciantes confiam muito nos documentos e talvez listar os padrões possíveis disponíveis para resolver todos os tipos de problemas seja exatamente o que você deve fazer. Podemos aprender padrões em profundidade por nós mesmos, aprender qual ferramenta é a certa para a tarefa é a parte difícil.

Quero tornar mais fáceis as coisas que eram difíceis para mim. Acho que vai ser uma questão de poucas linhas e pode ajudar os iniciantes no futuro.

Eu sempre acabo escrevendo comentários enormes .. Obrigado por ficar comigo e ler. :sorriso:

Olá @todos ,

Eu gostaria de reviver essa conversa adicionando outro ponto de vista. Wir react @ 16 é possível montar componentes em certos pontos do DOM usando Portals . Para este caso de uso, estou construindo diferentes componentes, como modais ou notificações, que devem ser renderizados em um determinado outro componente que é montado em meu App.jsx assim.

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

A outra opção seria encontrar o domNode com document.findElementById ou funções semelhantes e passá-los para ReactDOM.findDOMNode , o que me faz sentir muito desagradável, pois sou forçado a deixar o "React-Cosmos".

Portanto, eu adoraria ser capaz de pesquisar instâncias de um determinado componente que eu passo para a função, em vez de passar a própria instância, para o recurso mencionado acima. Também estou interessado em outras abordagens sobre como resolver esse problema.

@jimfb valeria a pena uma proposta de recurso?

Esta página foi útil?
0 / 5 - 0 avaliações