Redux: É possível armazenar um componente de reação dentro de um redutor?

Criado em 17 jan. 2016  ·  26Comentários  ·  Fonte: reduxjs/redux

Oi,

Tenho tentado armazenar um componente de reação dentro de um redutor para um projeto no qual estou trabalhando. Eu quero saber se está ok para fazer isso e como eu faria isso.

Tentei fazer, mas perde alguma funcionalidade dentro do redutor.

Um componente de reação seria mais ou menos assim:

{ function:
   { [Function: Connect]
     displayName: 'Connect(Counter)',
     WrappedComponent: { [Function: Counter] propTypes: [Object] },
     contextTypes: { store: [Object] },
     propTypes: { store: [Object] } } }

No entanto, depois de armazená-lo em um redutor, ele perde suas propriedades e fica com a seguinte aparência:

{ function:
   { [Function: Connect] } }

Comentários muito úteis

O que você _pode_ deseja fazer é fornecer IDs de string exclusivos para alguns componentes e armazenar esses IDs no estado. Por exemplo, você pode armazenar algo como ModalTypes.LOGIN em state.openModalId e, posteriormente, switch dentro de seu componente <App> para escolher qual componente modal exibir.

Todos 26 comentários

Você poderia explicar por que você precisa fazer isso?
Uma loja deve conter o estado do aplicativo serializável, não os componentes DOM, que são uma representação visual desse estado.

Nunca faça isso, consulte o conselho oficial.
O que não deve entrar no estado?

@simongfxu : +1:

Obrigado pelo esclarecimento @simongfxu

O que você _pode_ deseja fazer é fornecer IDs de string exclusivos para alguns componentes e armazenar esses IDs no estado. Por exemplo, você pode armazenar algo como ModalTypes.LOGIN em state.openModalId e, posteriormente, switch dentro de seu componente <App> para escolher qual componente modal exibir.

@gaearon sim, require o componente de reação quando necessário. Eu preciso habilitar e desabilitar componentes e redutores no comando.

Sei que esse problema está resolvido, mas gostaria de entrar em contato porque tenho um caso de uso semelhante.

Tenho uma loja chamada editor e uma chave nessa loja chamada activeTool . Esta chave contém uma string e funciona bem. No entanto, também tenho uma chave chamada toolbar ; nesta chave, gostaria de manter uma lista de classes de componentes que devem ser renderizadas com a ferramenta ativa.
Minha ação é mais ou menos assim:

{
  type: 'SELECT_TOOL',
  payload: {
    name: 'toolName',
    tools: [A, List, Of, Tools]
  }
}

Portanto, no redutor editor , direcionamos essa ação e fazemos algo como o seguinte (com js imutáveis, mas isso provavelmente não é importante):

return state
  .set('activeTool', payload.name)
  .set('toolBar', payload.tools)

No entanto, dev-tools relata o activeTool correto, mas toolBar foi excluído da loja editor . Basicamente, os mesmos sintomas da OP.

De qualquer forma, eu só queria divulgar meu caso de uso ....
Acabei renunciando ao uso da propriedade toolBar na loja e, agora, no componente que renderiza a barra de ferramentas, tenho um objeto que mapeia nomes de ferramentas com uma matriz de componentes.

Saúde!

@ oscar-g Você deve atribuir identificadores serializáveis ​​(string ou numéricos) às suas ferramentas - isso é o que você passará por meio de ações e armazenará na loja, não os próprios componentes do React.

Tenho um objeto que mapeia nomes de ferramentas com uma série de componentes.

Sim, este é o único caminho a percorrer.

Obrigado, @sompylasar. Acho que basicamente foi isso que acabei fazendo.

  1. action = {type: SELECT_TOOL, name: 'some string'}
  2. Coloque o nome na loja.
  3. Na renderização do componente: return (TOOLMAP[this.props.tool.name])

Onde as chaves em TOOLMAP mapeiam para matrizes de componentes. É apenas uma constante no arquivo do componente.

É isto que você quer dizer?

Sim, este é o caminho a percorrer.

@simongfxu seu link "O que não deveria

@Bartuz , @simongfxu : não tenho certeza se os novos documentos têm um equivalente a essa seção, na verdade.

Aqui está um link para a página original no Web Archive: React Docs: Interatividade e IUs dinâmicas . Além disso, aqui está o conteúdo original, citado:

O que _não_ deveria ir no estado?

this.state deve conter apenas a quantidade mínima de dados necessários para representar o estado da sua IU. Como tal, não deve conter:

  • Dados computados: não se preocupe com valores de pré-computação com base no estado - é mais fácil garantir que sua IU seja consistente se você fizer todos os cálculos dentro de render() . Por exemplo, se você tem um array de itens de lista no estado e deseja renderizar a contagem como uma string, simplesmente renderize this.state.listItems.length + ' list items' em seu método render() vez de armazená-lo no estado.
  • Componentes de reação: construa-os em render() base em adereços e estado subjacentes.
  • Dados duplicados dos adereços: tente usar os adereços como a fonte da verdade sempre que possível. Um uso válido para armazenar adereços no estado é poder saber seus valores anteriores, porque os adereços podem mudar com o tempo.

Meus 2 centavos:

  1. Tenho um aplicativo móvel com um único componente de cabeçalho que renderiza o título da página atual (com base em uma string na loja) e pode ou não ter alguns botões de ação específicos para a página atual (editar, salvar / cancelar, ações > lista suspensa com várias ações, etc). Este seria um caso de uso para passar componentes por meio da loja, por exemplo, cada página "injetando" seus próprios componentes na área do cabeçalho.
  2. A abordagem acima iria contra o fluxo para o qual React e Redux foram construídos e otimizados. Os portais oferecem uma alternativa atraente se você quiser, mas então você pula a loja. Isso pode ser bom ou ruim, dependendo de suas necessidades de monitoramento / registro. Usando o Redux, strings ou objetos com strings podem definir os botões, então uma string de 'ação' pode acionar o comportamento fazendo com que seu componente a ouça.

@Dindaleon Entendi e acho interessante, apesar do que sugere o React Doc oficial.

Eu tenho um problema similar. Não tenho certeza se abrir um exemplar é uma boa ideia.

Basicamente, tenho um sistema de plug-ins onde os plug-ins podem se registrar e podem adicionar novos componentes à IU. Eu atualmente os adiciono em um objeto 'componentes' dentro da loja. Eles são adicionados usando um criador de ação e armazenados lá usando a chave de carga útil. Os componentes da IU que permitem a adição de plug-ins, basta verificar na loja se algo foi adicionado. Se sim, eles puxam o componente de lá e o renderizam.

Eu li muito sobre como adicionar funções (redutores) / componentes de reação à loja. Mas não consegui encontrar uma boa solução para isso. Eu realmente não posso mapear os elementos da IU para um I, pois não tenho como saber cada elemento durante o tempo de compilação. E, de alguma forma, preciso de um mecanismo de registro para disponibilizar os novos elementos da IU para o aplicativo principal.

Alguém passou por uma situação semelhante? Como você os resolveu? Eu pesquisei muitos projetos de código aberto que alugam para ter um problema semelhante (átomo, por exemplo). Esses armazenam seus componentes em um ComponentStore (fluxo).

@SirWindfield : você pode querer dar uma olhada em: http://dylanpaulus.com/reactjs/2017/12/08/global-component-registration/ . Parece ser uma extensão da abordagem básica para lidar com pesquisas de componentes de IU em tempo de execução , apenas estendido para ter uma variável global e função de registro para adicionar a essa tabela em vez de tê-la escrita à mão.

Se precisar que isso esteja disponível no aplicativo, você também pode escrever seu próprio componente <Provider> -type que usa context do React para torná-lo disponível para componentes profundamente aninhados.

@markerikson obrigado pela resposta!
Na verdade, isso se parece muito com a ideia de fluxo que tive: sorriso:
É muito difícil encontrar recursos sobre este tópico. Parece que as pessoas geralmente não têm interesse em escrever sistemas de plugins usando redux e react.

@SirWindfield : É definitivamente um tópico menos conhecido, sim.

Dito isso, cataloguei várias bibliotecas do tipo "Redux plugin / encapsulation" em https://github.com/markerikson/redux-ecosystem-links/blob/master/component-state.md#modularity -and-encapsulation. Ainda não tive tempo de experimentar nenhum deles sozinha. Algum dia eu gostaria de poder fazer experiências com eles e ter uma ideia do que eles são capazes, mas eu simplesmente tenho muito mais o que fazer. Ainda assim, você pode querer dar uma olhada neles e ver se alguma coisa corresponde ao seu caso de uso.

@markerikson obrigado! Essa lista é incrível.

E se eu quiser armazenar no estado um objeto File, para fins de rastreamento de upload. Isso deve ficar bem?

Na verdade não, só posso armazenar objetos serializáveis.

Você pode armazenar o caminho do arquivo embora

@albanx potencialmente sim, você pode codificar o arquivo (base64) e armazená-lo sempre que desejar. A questão é: você realmente precisa armazenar um arquivo?

@SirWindfield Eu quis dizer um arquivo HTML5, Blob (quando o usuário seleciona um arquivo no navegador para fazer upload).
@soulclown Eu realmente não preciso do conteúdo do arquivo, mas apenas de uma referência ao elemento File. Estou criando um uploader e quero acompanhar os arquivos carregados e o andamento do estado. Vou acabar criando um ID para os arquivos e armazenando no estado.

Caso interessante, Alban. Mantenha-nos atualizados sobre quais são as suas soluções para isso

[imagem: Mailtrack]
https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5&
Remetente
notificado por
Mailtrack
https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality5&
01/08/18,
15:12:04

01/08/2018 10:28 GMT + 02: 00 Alban [email protected] :

@SirWindfield https://github.com/SirWindfield eu quis dizer um arquivo HTML5,
Blob (quando o usuário seleciona um arquivo no navegador para fazer upload).
@soulclown https://github.com/soulclown Eu realmente não preciso do
conteúdo para o arquivo, mas apenas uma referência ao elemento File. eu sou
criando um uploader e quero acompanhar os arquivos carregados e
progresso no estado. Vou acabar criando um ID para os arquivos e armazenamento
isso no estado.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/reduxjs/redux/issues/1248#issuecomment-409494273 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AEL3RHZQT-Kp-MLFoUZryI0hrals0MFaks5uMWa8gaJpZM4HGj-F
.

FWIW, como @markerikson meio que sugeriu em relação aos frameworks de plugins, estive armazenando componentes, redutores e middleware React em estado redux por anos usando meus pacotes react-features e react-redux-features , com SSR .

Funciona porque não serializo a parte dos recursos da árvore de estado que contém os componentes do React. Acabei de serializar quais ids de recursos foram carregados durante o SSR (esses são os ids globais únicos @gaearon
sugerido). Mas onde eu parti do consenso é que, ao inicializar o clientide, eu reconstruo a parte não serializável do zero, carregando o conteúdo para os ids de recursos aplicáveis.

A única desvantagem é que não funcionaria com a viagem no tempo. Mas em toda a minha depuração, eu nunca realmente desejei um depurador de viagem no tempo ... logs redux são bons o suficiente para mim.

Suponho que poderia mover o estado não serializável para um armazenamento separado de tipos com seu próprio provedor de contexto. Pode ser. Pode ser um PITA diferente, entretanto?

Cheguei a esse design porque ter um componente global separado e tabelas de pesquisa de redutor seria muito mais complicado de coordenar com o carregamento assíncrono de blocos.

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

Questões relacionadas

ilearnio picture ilearnio  ·  3Comentários

captbaritone picture captbaritone  ·  3Comentários

timdorr picture timdorr  ·  3Comentários

CellOcean picture CellOcean  ·  3Comentários

parallelthought picture parallelthought  ·  3Comentários