Redux e RxJS, alguma semelhança?

113

Eu sei que Redux é uma "implementação" melhor do Flux, ou melhor dizendo, é um redesenho para simplificar as coisas (gerenciamento de estado do aplicativo).

Já ouvi muito sobre programação reativa (RxJS), mas ainda não mergulhei para aprender.

Então, minha pergunta é: há alguma interseção (algo em comum) entre essas duas tecnologias ou elas são complementares? ... ou totalmente diferente?

Oswaldo
fonte

Respostas:

185

Em suma, são bibliotecas muito diferentes para propósitos muito diferentes, mas sim, existem algumas semelhanças vagas.

Redux é uma ferramenta de gerenciamento de estado em toda a aplicação. Geralmente é usado como uma arquitetura para UIs. Pense nisso como uma alternativa para (metade do) Angular.

RxJS é uma biblioteca de programação reativa. Geralmente é usado como uma ferramenta para realizar tarefas assíncronas em JavaScript. Pense nisso como uma alternativa às promessas.


A programação reativa é um paradigma (forma de trabalhar e pensar) onde as mudanças de dados são observadas à distância . Os dados não são alterados à distância .

Aqui está um exemplo de mudança à distância :

// In the controller.js file
model.set('name', 'George');

O modelo é alterado no controlador.

Aqui está um exemplo de observação à distância :

// logger.js
store.subscribe(function (data) {
    console.log(data);
});

No Logger, observamos as mudanças de dados que acontecem no Store (à distância) e gravamos no console.


Redux usa um pouco o paradigma reativo: a loja é reativa. Você não define seu conteúdo à distância. É por isso que não existe store.set()no Redux. A Loja observa as ações à distância e muda a si mesma. E a Loja permite que outros observem seus dados à distância.

RxJS também usa o paradigma Reativo, mas em vez de ser uma arquitetura, ele fornece blocos de construção básicos, Observáveis , para realizar esse padrão de "observação à distância".

Para concluir, coisas muito diferentes para diferentes propósitos, mas compartilhe algumas idéias.

André Staltz
fonte
4
Não, você não deve usá-los juntos. As pessoas emularam o Redux usando Rx. Um rápido Google encontrará exemplos para você. Se você quiser usar Rx para sua IU reativa, dê uma olhada no Cycle.js, o framework de Andre. Tenho usado ultimamente e é fantástico. A API mudou muito recentemente, mas acredito que ele finalmente está começando a congelar partes dela.
Joel Dentici
17
de acordo com os documentos oficiais redux , "Eles funcionam muito bem juntos."
galki
12
Eles funcionam muito bem juntos! Existe um middleware Redux que lhe dá a oportunidade de usar RxJS e Observables para ações Redux. github.com/redux-observable/redux-observable Além disso, escrevi uma postagem no blog sobre o How To: robinwieruch.de/redux-observable-rxjs
Robin Wieruch
1
O paradigma Redux ajudou a tornar minha base de código do projeto Android mais reativa. Nossos fluxos de dados vindos de botões e outros campos para atualizar um estado, em conjunto com RxJava, sobrecarregaram nossa legibilidade e desempenho. As bibliotecas definitivamente funcionam bem juntas e seus benefícios são independentes do idioma.
Kenny Worden
Eles funcionam muito bem juntos, mas na prática o Reactive pode fazer por você o que o Redux faria - sincronizar o estado dos seus componentes com o modelo, então geralmente não faz muito sentido usar os dois
Filip Sobczak
32

São coisas muito diferentes.

RxJS pode ser usado para fazer programação reativa e é uma biblioteca muito completa com mais de 250 operadores.

E Redux é conforme descrito no repositório github "Redux é um contêiner de estado previsível para aplicativos JavaScript".

Redux é apenas uma ferramenta para lidar com o estado em aplicativos. Mas, em comparação, você pode construir um aplicativo completo em apenas RxJS.

Espero que isto ajude :)

cmdv
fonte
3
Sua resposta também é boa @cmdv. Eu não vi quando estava escrevendo o meu.
André Staltz
4

Redux é apenas uma biblioteca de gerenciamento de estado que vem com padrões bem definidos para operações de atualização. Contanto que você siga os padrões, você pode manter o fluxo de dados lógico e fácil de raciocinar. Ele também traz a capacidade de aprimorar o fluxo de dados com middlewares e otimizadores de armazenamento.

RxJS é um kit de ferramentas para programação reativa. Você pode realmente pensar em tudo que está acontecendo em seu aplicativo como um fluxo. RxJS oferece um conjunto de ferramentas muito rico para gerenciar esses fluxos.

Onde RxJS e Redux interceptam? No redux você atualiza seu estado com ações e, obviamente, essas ações podem ser tratadas como fluxos. Usando um middleware como redux-observable (você não precisa), você pode implementar sua chamada "lógica de negócios" de uma forma reativa. Outra coisa é que você pode criar um observável em sua loja redux, o que às vezes pode ser mais fácil do que usar um realçador.

mdikici
fonte
2

Resumindo:

Redux: Biblioteca inspirada no Flux usada para Gerenciamento de Estado .

RxJS: É outra biblioteca Javascript baseada na filosofia de programação reativa, usada para lidar com "Streams" (Observáveis, etc.) [Leia sobre Programação Reativa para entender os conceitos de Stream].

Krishna Ganeriwal
fonte
1

Eu só queria adicionar algumas diferenças pragmáticas de quando fiz o código RxJS inspirado no Redux.

Mapeei cada tipo de ação para uma instância de Assunto. Cada componente com estado terá um Assunto que é mapeado em uma função redutora. Todos os fluxos do redutor são combinados com o estado mergee, em seguida, scangeram a saída. O valor padrão é definido startWithlogo antes de scan. Usei publishReplay(1)para estados, mas posso removê-lo mais tarde.

A função de renderização pura de reação será apenas para o local onde você produz dados de evento enviando todos os produtores / assuntos.

Se você tem componentes filhos, precisa descrever como esses estados são combinados com os seus. combineLatestpode ser um bom ponto de partida para isso.

Diferenças notáveis ​​na implementação:

  • Sem middleware, apenas operadores rxjs. Acho que esse é o maior poder e fraqueza. Você ainda pode pegar conceitos emprestados, mas acho difícil obter ajuda de comunidades irmãs como redux e cycle.js, uma vez que é outra solução customizada. É por isso que preciso escrever "eu" em vez de "nós" neste texto.

  • Sem opção / caso ou strings para tipos de ação. Você tem uma maneira mais dinâmica de separar ações.

  • rxjs pode ser usado como uma ferramenta em qualquer lugar e não está restrito ao gerenciamento de estado.

  • Menos número de produtores do que tipos de ação (?). Não tenho certeza sobre isso, mas você pode ter muitas reações nos componentes pai que ouvem os componentes filho. Isso significa menos código imperativo e menos complexidade.

  • Você possui a solução. Nenhuma estrutura necessária. Bom e mau. Você vai acabar escrevendo seu próprio framework de qualquer maneira.

  • É muito mais fractal, e você pode facilmente assinar as alterações de uma subárvore ou de várias partes da árvore de estado do aplicativo.

    • Adivinha o quão fácil é fazer épicos como o redux-obseravble fazem? Muito fácil.

Também estou trabalhando em benefícios muito maiores, onde os componentes filhos são descritos como fluxos. Isso significa que não precisamos completar os estados pai e filho nos redutores, já que podemos apenas ("apenas") combinar recursivamente os estados com base na estrutura do componente.

Eu também penso em pular o react e ir com snabbdom ou outra coisa até que o React trate melhor os estados reativos. Por que devemos construir nosso estado para cima apenas para quebrá-lo por meio de suportes novamente? Vou tentar fazer uma versão 2 desse padrão com Snabbdom.

Aqui está um trecho mais avançado, mas pequeno, onde o arquivo state.ts constrói o fluxo de estado. Este é o estado do componente do formulário ajax que obtém um objeto de campos (entradas) com regras de validação e estilos CSS. Neste arquivo, usamos apenas os nomes dos campos (chaves do objeto) para combinar todos os estados dos filhos no estado do formulário.

export default function create({
  Observable,
  ajaxInputs
}) {
  const fieldStreams = Object.keys(ajaxInputs)
  .map(function onMap(fieldName) {
    return ajaxInputs[fieldName].state.stream
    .map(function onMap(stateData) {
      return {stateData, fieldName}
    })
  })

  const stateStream = Observable.combineLatest(...fieldStreams)
  .map(function onMap(fieldStreamDataArray) {
    return fieldStreamDataArray.reduce(function onReduce(acc, fieldStreamData) {
    acc[fieldStreamData.fieldName] = fieldStreamData.stateData
    return acc
  }, {})
  })

  return {
    stream: stateStream
  }
}

Embora o código possa não dizer muito isoladamente, ele mostra como você pode construir o estado para cima e como pode produzir eventos dinâmicos com facilidade. O preço a pagar é que você precisa entender um estilo diferente de código. E adoro pagar esse preço.

Marcus Rådell
fonte
Um ano depois, acabei de encontrar sua resposta e acho que ainda é válida! Fiz algo semelhante e concordo com todos os seus pontos. Mas, de qualquer forma, uma pergunta: você ainda pensa o mesmo hoje, ou mudou desde então?
Xceno
1
Eu preciso revisar a crítica sobre switch / case e tipos de ação no Redux. Eu ainda faço código da mesma maneira, mas tentando trabalhar em como fazê-lo funcionar do lado do servidor. Quando se trata do código React, consegui fazer um pequeno utilitário que ajuda a criar os redutores / atualizadores. Ainda estou fazendo a mesma coisa, mas um pouco mais polida. A maior mudança é que eu deixei cada nó folha assinar o fluxo em componentDidMount e cancelar a assinatura em componentDidUnmount. Quero obter uma camada de serviço reativa que funcione no front-end e no back-end. Fazendo progresso lá.
Marcus Rådell