Se as lojas mantiverem seu próprio estado e tiverem a capacidade de chamar serviços de rede e armazenamento de dados ao fazê-lo ... nesse caso, as ações serão apenas passadores de mensagens idiotas,
-OU-
... as lojas devem ser idiotas de dados imutáveis das ações (e as ações são aquelas que buscam / enviam dados entre fontes externas? A loja, neste caso, atuaria como modelos de exibição e seria capaz de agregar / filtrar seus dados antes de definir sua própria base de estado nos dados imutáveis que foram alimentados pela ação.
Parece-me que deveria ser um ou outro (em vez de uma mistura de ambos). Se sim, por que um é preferido / recomendado em relação ao outro?
reactjs
reactjs-flux
plaxdan
fonte
fonte
Respostas:
Eu vi o padrão de fluxo implementado nos dois sentidos e, depois de ter feito as duas coisas (inicialmente seguindo a abordagem anterior), acredito que os armazenamentos devem ser destinatários burros dos dados das ações e que o processamento assíncrono de gravações deve viver no criadores de ação. ( Async leituras podem ser tratadas de maneira diferente .) Na minha experiência, isso tem alguns benefícios, em ordem de importância:
Suas lojas se tornam completamente síncronas. Isso torna a lógica da sua loja muito mais fácil de seguir e muito fácil de testar - basta instanciar uma loja com um determinado estado, enviar uma ação e verificar se o estado mudou conforme o esperado. Além disso, um dos conceitos principais do fluxo é impedir despachos em cascata e impedir vários despachos de uma só vez; isso é muito difícil de fazer quando suas lojas fazem processamento assíncrono.
Todos os despachos de ação acontecem dos criadores da ação. Se você manipula operações assíncronas em suas lojas e deseja manter os manipuladores de ação de suas lojas síncronos (e você deve obter as garantias de envio único de fluxo), suas lojas precisarão acionar ações adicionais de SUCESSO e FAIL em resposta a assíncronas em processamento. Colocar esses despachos nos criadores de ações ajuda a separar os trabalhos dos criadores de ações e das lojas; além disso, você não precisa procurar na lógica da sua loja para descobrir de onde as ações estão sendo despachadas. Uma ação assíncrona típica nesse caso pode ser algo assim (altere a sintaxe das
dispatch
chamadas com base no sabor do fluxo que você está usando):A lógica que pode ser duplicada em várias ações deve ser extraída em um módulo separado; neste exemplo, seria esse módulo
SomeDataAccessLayer
, que lida com a solicitação real do Ajax.Você precisa de menos criadores de ação. Isso é menos importante, mas é bom ter. Conforme mencionado no item 2, se suas lojas tiverem manipulação de envio de ação síncrona (e deveriam), você precisará disparar ações extras para lidar com os resultados de operações assíncronas. Fazer os despachos nos criadores de ação significa que um único criador de ação pode despachar todos os três tipos de ação manipulando o resultado do próprio acesso assíncrono aos dados.
fonte
"SOME_ACTION"
), usar uma API para fazer uma solicitação (SomeDataAccessLayer.doSomething(userId)
) que retorne uma promessa e, nas duas.then
funções, despachar ações adicionais. O estado da solicitação pode (mais ou menos) mapear para armazenar o estado, se o aplicativo precisar saber sobre o status do estado. Como este mapas é até o aplicativo (por exemplo, talvez cada comentário tem um estado erro individual, a la Facebook, ou talvez haja um componente de erro global)Eu twittou esta pergunta para os desenvolvedores no Facebook e a resposta que recebi de Bill Fisher foi:
fonte
a call from store works better when action triggers from non-human driver
?As lojas devem fazer tudo, incluindo buscar dados e sinalizar para os componentes que os dados da loja foram atualizados. Por quê? Como as ações podem ser leves, descartáveis e substituíveis sem influenciar comportamentos importantes. Todos os comportamentos e funcionalidades importantes acontecem na loja. Isso também evita a duplicação de comportamentos que, de outra forma, seriam copiados em duas ações muito semelhantes, mas diferentes. As lojas são sua única fonte de (lidar com a) verdade.
Em todas as implementações do Flux que vi, Actions são basicamente cadeias de eventos transformadas em objetos, como tradicionalmente você teria um evento chamado "anchor: clicked", mas no Flux seria definido como AnchorActions.Clicked. Eles são tão "burros" que a maioria das implementações tem objetos Dispatcher separados para realmente despachar os eventos para as lojas que estão ouvindo.
Pessoalmente, gosto da implementação do Flux pelo Reflux, onde não há objetos Dispatcher separados e os objetos Action fazem o envio por eles mesmos.
edit: O Flux do Facebook, na verdade, busca "criadores de ação", para que eles usem ações inteligentes. Eles também preparam a carga útil usando as lojas:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/actions/ChatMessageActionCreators.js#L27 (linhas 27 e 28)
O retorno de chamada na conclusão acionaria uma nova ação dessa vez com os dados buscados como carga útil:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/utils/ChatWebAPIUtils.js#L51
Então acho que essa é a melhor solução.
fonte
Fornecerei um argumento a favor de ações "burras".
Ao colocar a responsabilidade de coletar dados de exibição em suas Ações, você as associa aos requisitos de dados de suas visualizações.
Por outro lado, as Ações genéricas, que descrevem declarativamente a intenção do usuário, ou alguma transição de estado em seu aplicativo, permitem que qualquer Loja que responda a essa Ação transforme a intenção em um estado personalizado especificamente para as visualizações nele subscritas.
Isso se presta a lojas mais numerosas, porém menores e mais especializadas. Eu argumento por esse estilo porque
O objetivo de uma loja é fornecer dados para visualizações. O nome "Ação" sugere para mim que seu objetivo é descrever uma alteração no meu Aplicativo.
Suponha que você precise adicionar um widget a uma exibição existente do Painel, que mostra alguns novos dados agregados sofisticados que sua equipe de back-end acabou de lançar.
Com as ações "inteligentes", pode ser necessário alterar a ação do "painel de atualização" para consumir a nova API. No entanto, "Atualizando o painel" em um sentido abstrato não mudou. Os requisitos de dados de suas visualizações são o que mudou.
Com Ações "burras", você pode adicionar uma nova Loja para o novo widget consumir e configurá-la para que, quando receber o tipo de ação "painel de atualização", envie uma solicitação para os novos dados e a exponha a o novo widget quando estiver pronto. Faz sentido para mim que, quando a camada de visualização precisar de mais ou de dados diferentes, as coisas que eu altero serão as fontes desses dados: Lojas.
fonte
O flux- react -router-demo da gaeron possui uma boa variação de utilidade da abordagem 'correta'.
Um ActionCreator gera uma promessa de um serviço de API externo e passa a promessa e três constantes de ação para uma
dispatchAsync
função em um Proxy / Dispatcher estendido.dispatchAsync
sempre enviará a primeira ação, por exemplo, 'GET_EXTERNAL_DATA' e, uma vez que a promessa retorne, enviará 'GET_EXTERNAL_DATA_SUCCESS' ou 'GET_EXTERNAL_DATA_ERROR'.fonte
Se você quer um dia ter um ambiente de desenvolvimento comparável ao que você vê no famoso vídeo Inventando sobre princípios , de Bret Victor , você deve usar lojas idiotas que são apenas uma projeção de ações / eventos dentro de uma estrutura de dados, sem nenhum efeito colateral. Também ajudaria se suas lojas fossem realmente membros da mesma estrutura global de dados imutáveis, como no Redux .
Mais explicações aqui: https://stackoverflow.com/a/31388262/82609
fonte