Redux i RxJS, jakieś podobieństwa?

113

Wiem, że Redux jest lepszą "implementacją" Fluxa, albo lepiej mówiąc, że jest to przeprojektowanie mające na celu uproszczenie rzeczy (zarządzanie stanem aplikacji).

Wiele słyszałem o programowaniu reaktywnym (RxJS), ale jeszcze nie nurkowałem, aby się go nauczyć.

Więc moje pytanie brzmi: czy są jakieś przecięcia (coś wspólnego) między tymi dwiema technologiami, czy też się uzupełniają? ... czy zupełnie inaczej?

Oswaldo
źródło

Odpowiedzi:

185

Krótko mówiąc, są to bardzo różne biblioteki do bardzo różnych celów, ale tak, istnieją pewne niejasne podobieństwa.

Redux to narzędzie do zarządzania stanem w całej aplikacji. Zwykle jest używany jako architektura interfejsów użytkownika. Potraktuj to jako alternatywę dla (połowy) Angulara.

RxJS to reaktywna biblioteka programistyczna. Zwykle jest używany jako narzędzie do wykonywania zadań asynchronicznych w JavaScript. Potraktuj to jako alternatywę dla obietnic.


Programowanie reaktywne to paradygmat (sposób pracy i myślenia), w którym zmiany danych są obserwowane z daleka . Dane nie są zmieniane na odległość .

Oto przykład zmiany na odległość :

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

Model jest zmieniane od kontrolera.

Oto przykład obserwacji z daleka :

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

W Loggerze obserwujemy zmiany danych zachodzące w Sklepie (z daleka) i piszemy do konsoli.


Redux używa paradygmatu Reactive tylko trochę: Sklep jest reaktywny. Nie ustawiasz jego treści na odległość. Dlatego store.set()w Redux nie ma . Sklep obserwuje poczynania z dystansu i sam się zmienia. A Sklep pozwala innym obserwować jego dane z daleka.

RxJS również używa paradygmatu reaktywnego, ale zamiast być architekturą, daje podstawowe bloki konstrukcyjne, Observables , aby osiągnąć ten wzorzec „obserwacji na odległość”.

Podsumowując, bardzo różne rzeczy do różnych celów, ale podziel się kilkoma pomysłami.

André Staltz
źródło
4
Nie, nie powinieneś ich używać razem. Ludzie emulowali Redux za pomocą Rx. Szybkie Google znajdzie dla Ciebie przykłady. Jeśli chcesz używać Rx do swojego reaktywnego interfejsu użytkownika, sprawdź Cycle.js, framework Andre. Ostatnio go używam i jest fantastyczny. API bardzo się ostatnio zmieniało, ale wydaje mi się, że w końcu zaczyna zamrażać jego część.
Joel Dentici
17
według oficjalnych dokumentów Redux: „Świetnie ze sobą współpracują”.
galki
12
Świetnie razem pracują! Istnieje oprogramowanie pośredniczące Redux, które daje możliwość użycia RxJS i Observables do działań Redux. github.com/redux-observable/redux-observable Dodatkowo napisałem wpis na blogu o Poradniku
Robin Wieruch
1
Paradygmat Redux pomógł uczynić mój kod projektu na Androida bardziej reaktywnym. Nasze przepływy danych pochodzące z przycisków i innych pól w celu aktualizacji stanu, w połączeniu z RxJava, zwiększyły naszą czytelność i wydajność. Biblioteki zdecydowanie dobrze ze sobą współpracują, a ich zalety są niezależne od języka.
Kenny Worden,
Świetnie ze sobą współpracują, ale w praktyce Reactive może zrobić dla ciebie to, co zrobiłby Redux - zsynchronizować stan twoich komponentów z modelem, więc często nie ma sensu używać obu
Filip Sobczak
32

To bardzo różne rzeczy.

RxJS może być używany do programowania reaktywnego i jest bardzo dokładną biblioteką z ponad 250 operatorami.

Redux jest taki, jak opisano w repozytorium github „Redux to przewidywalny kontener stanu dla aplikacji JavaScript”.

Redux to tylko narzędzie do obsługi stanu w aplikacjach. Ale dla porównania możesz zbudować pełną aplikację w samym RxJS.

Mam nadzieję że to pomoże :)

cmdv
źródło
3
Twoja odpowiedź też jest dobra @cmdv. Nie widziałem tego, kiedy pisałem swoje.
André Staltz
4

Redux to po prostu biblioteka do zarządzania stanem, zawierająca dobrze zdefiniowane standardy operacji aktualizacji. Jeśli trzymasz się standardów, możesz zachować rozsądny przepływ danych i łatwo go uzasadnić. Daje również możliwość usprawnienia przepływu danych dzięki oprogramowaniu pośredniczącemu i ulepszeniom magazynu.

RxJS to zestaw narzędzi do programowania reaktywnego. Możesz myśleć o wszystkim, co dzieje się w Twojej aplikacji, jako o strumieniu. RxJS daje bardzo bogaty zestaw narzędzi do zarządzania tymi strumieniami.

Gdzie przechwytuje RxJS i Redux? W redux aktualizujesz swój stan akcjami i oczywiście te działania mogą być traktowane jako strumienie. Korzystając z oprogramowania pośredniego, takiego jak redux-observable (nie musisz), możesz zaimplementować swoją tak zwaną „logikę biznesową” w sposób reaktywny. Inną rzeczą jest to, że możesz stworzyć obserwowalne ze swojego sklepu Redux, co czasami może być łatwiejsze niż użycie wzmacniacza.

mdikici
źródło
2

Krótko mówiąc:

Redux: Biblioteka inspirowana Flux używana do zarządzania stanem .

RxJS: Jest to kolejna biblioteka JavaScript oparta na filozofii programowania reaktywnego, używana do radzenia sobie ze „strumieniami” (obserwowalne itp.) [Przeczytaj o programowaniu reaktywnym, aby zrozumieć koncepcje strumienia].

Krishna Ganeriwal
źródło
1

Chciałem tylko dodać kilka pragmatycznych różnic od czasu, gdy tworzyłem kod RxJS inspirowany Redux.

Każdy typ akcji odwzorowałem na instancję Subject. Każdy składnik stanowy będzie miał Subject, który jest następnie mapowany na funkcję redukującą. Wszystkie strumienie reduktora są łączone z, mergea następnie scanwyprowadzają stan. Wartość domyślna jest ustawiana startWithtuż przed scan. Użyłem publishReplay(1)dla stanów, ale mogę go później usunąć.

Funkcja reaktora czystego renderowania będzie polegała tylko na tym, aby umieścić dane zdarzenia, wysyłając wszystkich producentów / tematy.

Jeśli masz komponenty potomne, musisz opisać, jak te stany są łączone w twoje. combineLatestmoże być do tego dobrym punktem wyjścia.

Istotne różnice we wdrożeniu:

  • Brak oprogramowania pośredniego, tylko operatorzy rxjs. Myślę, że to największa siła i słabość. Nadal możesz pożyczać koncepcje, ale trudno jest mi uzyskać pomoc od siostrzanych społeczności, takich jak redux i cycle.js, ponieważ jest to kolejne niestandardowe rozwiązanie. Dlatego muszę w tym tekście napisać „ja” zamiast „my”.

  • Brak przełącznika / przypadku lub ciągów dla typów akcji. Masz bardziej dynamiczny sposób rozdzielania działań.

  • rxjs może być używany jako narzędzie w innym miejscu i nie jest zawarty w zarządzaniu stanem.

  • Mniejsza liczba producentów niż typów działań (?). Nie jestem tego pewien, ale możesz mieć wiele reakcji w komponentach nadrzędnych, które słuchają komponentów potomnych. Oznacza to mniej imperatywnego kodu i mniejszą złożoność.

  • Jesteś właścicielem rozwiązania. Żadne ramy nie są potrzebne. Dobry i zły. W końcu i tak napiszesz własny framework.

  • Jest to znacznie bardziej fraktalne i możesz łatwo subskrybować zmiany z poddrzewa lub wielu części drzewa stanu aplikacji.

    • Zgadnij, jak łatwo jest robić epiki tak, jak robią to redux-obseravable? Naprawdę proste.

Pracuję również nad znacznie większymi korzyściami, w których komponenty podrzędne są opisywane jako strumienie. Oznacza to, że nie musimy w reduktorach uzupełniać stanu rodzica i dziecka, ponieważ możemy po prostu („tylko”) rekurencyjnie łączyć stany na podstawie struktury komponentu.

Myślę też o pominięciu reagowania i przechodzenia ze snabbdom lub czymś innym, dopóki React lepiej nie poradzi sobie ze stanami reaktywnymi. Dlaczego mielibyśmy budować nasz stan w górę tylko po to, aby ponownie go rozbić za pomocą rekwizytów? Więc spróbuję stworzyć wersję 2 tego wzorca za pomocą Snabbdom.

Oto bardziej zaawansowany, ale mały fragment, w którym plik state.ts buduje strumień stanu. To jest stan komponentu ajax-form, który pobiera obiekt pól (danych wejściowych) z regułami walidacji i stylami CSS. W tym pliku używamy po prostu nazw pól (kluczy obiektów), aby połączyć wszystkie stany dzieci w stan formularza.

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

Chociaż kod może nie mówić wiele w izolacji, pokazuje, jak można budować stan w górę i jak z łatwością tworzyć dynamiczne zdarzenia. Cena do zapłacenia polega na tym, że musisz zrozumieć inny styl kodu. Uwielbiam płacić tę cenę.

Marcus Rådell
źródło
Minął rok później, właśnie znalazłem twoją odpowiedź i myślę, że nadal jest aktualna! Zrobiłem coś podobnego i zgadzam się ze wszystkimi twoimi punktami. Ale w każdym razie pytanie: czy nadal myślisz tak samo dzisiaj, czy od tego czasu ruszyłeś dalej?
Xceno
1
Muszę zrewidować krytykę dotyczącą przełącznika / przypadku i typów akcji w Redux. Nadal tworzę kod w ten sam sposób, ale próbuję pracować nad tym, jak sprawić, by działał po stronie serwera. Jeśli chodzi o kod Reacta, udało mi się zrobić małe narzędzie, które pomaga tworzyć reduktory / aktualizatory. Więc nadal robię to samo, ale trochę bardziej dopracowane. Największą zmianą jest to, że pozwoliłem każdemu węzłowi-liścowi subskrybować strumień na stronie componentDidMount i anuluję subskrypcję na componentDidUnmount. Chcę również uzyskać reaktywną warstwę usług, która działa na frontendzie i backendzie. Robi postępy.
Marcus Rådell