Qual é a diferença real entre redux e uma máquina de estado (por exemplo, xstate)?

93

Estou trabalhando na investigação de um aplicativo front-end de complexidade média. No momento, ele está escrito em javascript puro, e possui várias mensagens diferentes baseadas em eventos conectando algumas partes principais deste aplicativo.

Decidimos que precisamos implementar algum tipo de contêiner de estado para este aplicativo no escopo de refatoração adicional. Anteriormente, tive alguma experiência com redux e ngrx store (que na verdade segue os mesmos princípios).

Redux é uma opção para nós, mas um dos desenvolvedores propôs usar uma biblioteca baseada em máquina de estado, em particular a biblioteca xstate .

Nunca trabalhei com xstate, então achei interessante e comecei a ler a documentação e a olhar para diferentes exemplos. Parecia promissor e poderoso, mas em algum momento entendi que não vejo nenhuma diferença significativa entre ele e redux.

Passei horas tentando encontrar uma resposta, ou qualquer outra informação comparando xstate e redux. Não encontrei nenhuma informação clara, exceto alguns artigos como "get from redux to a state machine" , ou links para bibliotecas focadas em usar redux e xstate juntos (bastante estranho).

Se alguém puder descrever a diferença ou me dizer quando os desenvolvedores devem escolher o xstate - você é bem-vindo.

Artem Arkhipov
fonte
3
Os documentos oficiais realmente dizem que você deve tratar seus redutores redux como uma máquina de estado redux.js.org/style-guide/…
Yannic Hamann
Acho que as bibliotecas que você mencionou podem ser para usar o xstate como um sistema de gerenciamento de efeitos (alternativa para thunk, saga, epic, etc.)
Alfred Young

Respostas:

205

Criei o XState, mas não direi se devo usar um em vez do outro; isso depende da sua equipe. Em vez disso, tentarei destacar algumas diferenças importantes.

  • Redux é essencialmente um contêiner de estado onde eventos (chamados de ações no Redux) são enviados a um redutor que atualiza o estado.
  • XState é também um recipiente de estado, mas que se separa de estados finitos (por exemplo, "loading", "success") a partir de "estado infinita", ou de contexto (por exemplo, items: [...]).
  • Redux não dita como você define seus redutores. Elas são funções simples que retornam o próximo estado dado o estado atual e evento (ação).
  • XState é um "redutor com regras" - você define transições legais entre estados finitos devido a eventos, e também quais ações devem ser executadas em uma transição (ou na entrada / saída de um estado)
  • O Redux não tem uma maneira embutida de lidar com os efeitos colaterais. Existem muitas opções de comunidade, como redux-thunk, redux-saga, etc.
  • O XState torna as ações (efeitos colaterais) declarativas e explícitas - elas são parte do Stateobjeto que é retornado em cada transição (estado atual + evento).
  • Redux atualmente não tem como visualizar as transições entre os estados, uma vez que não faz distinção entre o estado finito e o infinito.
  • O XState possui um visualizador: https://statecharts.github.io/xstate-viz que é viável devido à natureza declarativa.
  • A lógica / comportamento implícito representado nos redutores Redux não pode ser serializado declarativamente (por exemplo, em JSON)
  • As definições de máquina do XState, que representam lógica / comportamento, podem ser serializadas em JSON e lidas em JSON. Isso torna o comportamento muito portátil e configurável por ferramentas externas.
  • Redux não é estritamente uma máquina de estado.
  • XState segue estritamente a especificação W3C SCXML: https://www.w3.org/TR/scxml/
  • Redux depende do desenvolvedor para prevenir manualmente estados impossíveis.
  • O XState usa gráficos de estados para definir naturalmente os limites para o tratamento de eventos, o que evita estados impossíveis e podem ser analisados ​​estaticamente.
  • Redux incentiva o uso de um único armazenamento atômico "global".
  • O XState incentiva o uso de uma abordagem semelhante ao modelo de ator, em que pode haver muitas instâncias hierárquicas de gráfico de estado / "serviço" que se comunicam entre si.

Adicionarei mais diferenças importantes aos documentos esta semana.

David Khourshid
fonte
6
Finalmente alguém usando FSM e SCXML para desenvolvimento frontal ... cara, você salvou minha vida, vou estudar sua biblioteca. Não gosto de redux por alguns motivos (primeiro confunde os termos de evento e ação) e, em segundo lugar, "modela" estados complexos com milhões de sinalizadores (prolixo e incorreto).
Carlos Verdes
1
@ Mike76 XState se integra com ferramentas de desenvolvimento Redux.
David Khourshid,
Obrigado pela dica, vou olhar para isso.
Mike76,
1
Agora tentei XState + Redux DevTools. Funciona muito bem, mas parecem faltar alguns recursos. Por exemplo, XState + Redux DevTools não oferece suporte a recursos como "reprodução de estado", em que uma sequência de estados anteriores é reproduzida. Isso se deve a limitações de implementação?
Mike76 de
21

A máquina de estado não informa (força) a ter fluxo de dados unidirecional. Não tem nada a ver com fluxo de dados. É mais sobre como restringir as mudanças de estado e sobre as transições de estado . Portanto, geralmente apenas algumas partes do aplicativo seriam projetadas com máquinas de estado, apenas e somente se você precisar restringir / proibir algumas mudanças de estado e estiver interessado nas transições.

Esteja ciente de que com máquinas de estado, se por algum motivo (dependência de API externa etc ...), houver chance do aplicativo travar em um estado em que não pode fazer a transição para outro estado devido a restrições, você terá que resolvê-lo.

Mas se você está interessado apenas no último estado do aplicativo em si, em vez de transições de estado , e as restrições de estado não importam, então é melhor não usar a máquina de estado e atualizar diretamente o estado em si ( você ainda pode agrupar o estado em uma atualização de classe Singleton por meio Aulas de ação ).


Por outro lado, Redux é um framework de arquitetura unidirecional . As arquiteturas unidirecionais impõem que você tenha uma direção única de fluxo de dados. No Redux, ele começa com User->View->(Action)->Store->Reducer->(Middleware)->Store->(State)->View. Como State Machines, você pode desencadear efeitos colaterais com Middlewares no Redux. Você pode restringir / proibir as transições de estado, se desejar. Diferente da State Machine , Redux força o fluxo de dados unidirecional, puro ! funções redutoras, objetos de estado imutáveis, estado único de aplicativo observável.

Jemshit Iskenderov
fonte