React-Redux: Czy wszystkie stany składników mają być przechowywane w sklepie Redux

89

Powiedz, że mam prosty przełącznik:

Kiedy klikam przycisk, składnik Kolor zmienia się z czerwonego na niebieski

Mogę osiągnąć ten wynik, robiąc coś takiego.

index.js

Button: onClick={()=>{dispatch(changeColor())}}
Color: this.props.color ? blue : red

container.js

connect(mapStateToProps)(indexPage)

action_creator.js

function changeColor(){
 return {type: 'CHANGE_COLOR'}
}

reduktor.js

switch(){
case 'CHANGE_COLOR':
return {color: true}

ale to jest cholernie dużo kodu do napisania dla czegoś, co mógłbym osiągnąć w 5 sekund z jQuery, niektórymi klasami i niektórymi css ...

Więc myślę, że tak naprawdę pytam, co ja tu robię źle?

l2silver
źródło
6
React-Redux nie jest sprzedawany jako produkt krótszy niż jquery. Zdecydowanie potrzebuje kodu, aby go uruchomić i uruchomić.
zerkms
1
Zajrzyj tutaj: github.com/rackt/redux/issues/1287 jest dużo dobrej dyskusji na ten temat.
m0meni
1
dzięki @ AR7, to jest idealne
l2silver
1
@ l2silver nie ma problemu. Zasadniczo chodzi o to, że jeśli kolor tego komponentu nie ma znaczenia dla nikogo innego, po prostu utrzymuj ten stan wewnątrz samego komponentu.
m0meni
2
problem, o którym wspomina AR7, został przeniesiony: github.com/reactjs/redux/issues/1287
ptim,

Odpowiedzi:

156

Redux jest przeznaczony głównie dla „stanu aplikacji”. To znaczy wszystko, co jest związane z logiką aplikacji. Widok zbudowany na nim jest odbiciem tego stanu, ale nie musi wyłącznie używać tego kontenera stanu do wszystkiego, co robi.

Wystarczy zadać następujące pytania: Czy ten stan ma znaczenie dla reszty aplikacji? Czy inne części aplikacji będą zachowywać się inaczej w zależności od tego stanu? W wielu drobnych przypadkach tak nie jest. Rozwiń menu: Fakt, że jest otwarty lub zamknięty, prawdopodobnie nie będzie miał wpływu na inne części aplikacji. Więc podłączenie go do twojego sklepu to prawdopodobnie przesada. Z pewnością jest to ważna opcja, ale tak naprawdę nie zapewnia żadnych korzyści. Lepiej jest używać this.statei nazywać to codziennie.

W twoim konkretnym przykładzie, czy kolor tego przycisku jest przełączany, aby wpłynąć na inne części aplikacji? Jeśli jest to jakiś globalny przełącznik włączania / wyłączania dla większej części aplikacji, to zdecydowanie należy do sklepu. Ale jeśli po prostu przełączasz kolor przycisku po kliknięciu przycisku, możesz pozostawić stan koloru zdefiniowany lokalnie. Akcja kliknięcia przycisku może mieć inne efekty, które wymagają wysłania akcji, ale jest to niezależne od prostego pytania, jakiego koloru powinien być.

Ogólnie staraj się, aby stan aplikacji był jak najmniejszy. Nie musisz tam wszystkiego wrzucać . Rób to, kiedy musisz, albo warto coś tam zatrzymać. Lub jeśli ułatwi Ci to życie podczas korzystania z narzędzi deweloperskich. Ale nie przeciążaj zbytnio jego znaczenia.

Tim Dorr
źródło
Hej, wiem, że nigdy nie będzie ostatecznej odpowiedzi na to pytanie, ale myślę, że twoja logika jest tutaj bardzo rozsądna
l2silver
3
Szczerze mówiąc, tak naprawdę nie rozumiem, po co w ogóle używać tego strumienia / reduxu. Jaki był problem z modelem sterowanym zdarzeniami?
jayarjo
IMO, to nie jest doskonała odpowiedź. To zależy. Przechowywanie stanu interfejsu użytkownika do stanu reagowania spowoduje, że magazyn Redux będzie czysty, ale skończy się na niefunkcjonalnym komponencie, który jest trudny do przetestowania. Przechowywanie stanu interfejsu użytkownika do stanu reagowania będzie wymagało dużego wysiłku na programistę, ponieważ musimy napisać dodatkowe redukcje. Istnieje jednak wiele pakietów, które mogą pomóc w znacznie łatwiejszym przechowywaniu stanu interfejsu użytkownika w sklepie redux. Więcej informacji można znaleźć na stronie redux.js.org/docs/faq/OrganizingState.html .
Ron
19

Redux FAQ: Organizacja
Podaj, że ta część oficjalnego dokumentu redux dobrze odpowiedziała na twoje pytanie.

Używanie stanu komponentu lokalnego jest w porządku . Twoim zadaniem jako programisty jest określenie, jakie stany składają się na Twoją aplikację i gdzie powinny znajdować się poszczególne elementy stanu. Znajdź równowagę, która Ci odpowiada i idź z nią.

Kilka typowych reguł określania, jakie dane powinny zostać umieszczone w Redux:

  • Czy inne części aplikacji dbają o te dane?
  • Czy musisz mieć możliwość tworzenia dalszych danych pochodnych na podstawie tych oryginalnych danych?
  • Czy te same dane są używane do obsługi wielu komponentów?
  • Czy przywracanie tego stanu do określonego punktu w czasie ma dla Ciebie wartość (tj. Debugowanie podróży w czasie)?
  • Czy chcesz buforować dane (tj. Użyć tego, co jest w stanie, jeśli już tam są, zamiast ponownie o nie poprosić)?
chuck911
źródło
6

W celu podkreślenia świetnego linku dostarczonego przez @ AR7 i ponieważ ten link został przesunięty jakiś czas temu:

Użyj React, aby uzyskać efemeryczny stan, który nie ma znaczenia dla aplikacji na całym świecie i nie zmienia się w skomplikowany sposób. Na przykład przełącznik w jakimś elemencie interfejsu użytkownika, stan wejścia formularza. Użyj Redux dla stanu, który ma znaczenie globalne lub jest zmutowany w złożony sposób. Na przykład użytkownicy z pamięci podręcznej lub wersja robocza posta.

Czasami będziesz chciał przejść ze stanu Redux do stanu React (gdy przechowywanie czegoś w Redux staje się niewygodne) lub odwrotnie (gdy więcej komponentów musi mieć dostęp do jakiegoś stanu, który był wcześniej lokalny).

Ogólna zasada brzmi: rób wszystko, co jest mniej niezręczne.

Dan Abramov: https://github.com/reactjs/redux/issues/1287#issuecomment-175351978

ptim
źródło
-8

Tak, warto dążyć do przechowywania stanu wszystkich komponentów w Redux . Jeśli to zrobisz, skorzystasz z wielu funkcji Redux, takich jak debugowanie podróży w czasie i powtarzalne raporty o błędach. Jeśli tego nie zrobisz, te funkcje mogą być całkowicie bezużyteczne .

Za każdym razem, gdy nie zapiszesz zmiany stanu składnika w Redux, ta zmiana zostanie całkowicie utracona ze stosu zmian Redux, a interfejs użytkownika aplikacji nie będzie zsynchronizowany ze sklepem. Jeśli to nie jest dla Ciebie ważne, zadaj sobie pytanie, po co w ogóle używać Redux? Bez niej Twoja aplikacja będzie mniej złożona!

Ze względu na wydajność możesz chcieć wrócić do this.setState()czegokolwiek, co spowodowałoby wielokrotne wywołanie wielu działań. Na przykład: przechowywanie stanu pola wejściowego w Redux za każdym razem, gdy użytkownik wpisze klucz, może spowodować niską wydajność. Możesz rozwiązać ten problem, traktując to jak transakcję: gdy akcja użytkownika zostanie „zatwierdzona”, zapisz stan końcowy w Redux.

Twój oryginalny post wspomina o tym, że sposób Redux to „piekielnie dużo kodu do napisania”. Tak, ale można używać abstrakcji dla typowych wzorców, takich jak stan komponentu lokalnego.

kumar303
źródło
Ulepszone debugowanie jest użytecznym celem i przyjemną cechą redukcji, ale myślę, że stosunek sygnału do szumu jest również ważny. Można by rejestrować każdą zmienną w bazie kodu, ale dodałoby to dużo dodatkowego kodu, czyniąc rzeczywisty kod trudniejszym do odczytania, a rejestrowanie byłoby trudne do przeszukania. Myślę, że to samo dotyczy stosowania Redux. Posiadanie wszystkich stanów w redux może usprawnić debugowanie, ale dodatkowy kod i abstrakcje mają koszt, który może utrudnić odczyt kodu, a nawet utrudnić niektóre zadania debugowania. (A kiedy narzędzia programistyczne redux ulegną awarii, wiele korzyści związanych z debugowaniem zostaje utraconych.)
JD Sandifer
1
Po co więc w ogóle używać Redux? Jeśli nie umieścisz wszystkiego w Redux, stracisz wszystkie funkcje, takie jak devtools. To naprawdę wszystko albo nic. Jeśli używasz setState () jako menu rozwijanego, takiego jak w pierwszej odpowiedzi na ten post, nie możesz używać devtools do debugowania żadnych problemów, które użytkownicy mogą napotkać w menu rozwijanym. Gorzej, gdy używasz setState () jako nakładki, ponieważ nie ma możliwości podróżowania w czasie przed i po wyświetleniu nakładki. Zraszanie setState () tutaj i tam jest bardzo podatne na błędy, ponieważ deweloper musi ciągle myśleć o tym, co może się zepsuć.
kumar303
Bardziej szczegółowa odpowiedź: rejestrowanie każdej zmiennej w bazie kodu nie jest przydatną metaforą, ponieważ pytanie dotyczy tego, czy użyć, this.setState()czy dispatch(action...). Nie trzeba go używać this.setState()wszędzie, ale kiedy trzeba, proponuję zamiast tego użyć Reduxa w 99% przypadków, wracając do this.setState()1% w oparciu o obawy dotyczące wydajności.
kumar303
Rejestrowanie każdej zmiennej wydaje mi się być analogiczne do umieszczania wszystkiego w Redux i równie niewskazane co do zasady. Pozostawienie niektórych rzeczy poza Reduxem nie neguje funkcji wszystkiego, co jest w Redux, o ile stan jest oddzielony. Oznacza to, że nadal mogę debugować logikę wywołań interfejsu API przesyłaną potokiem przez Redux, nawet jeśli stan pola wyboru nie jest. OP ma rację - wymaga więcej kodu w wielu miejscach, aby użyć Redux i może nie jest to uzasadnione w konkretnym przykładzie, który wymienili.
JD Sandifer
W rzeczywistości możesz nie być w stanie debugować logiki interfejsu API. To mój punkt. Naprawdę trudno jest przewidzieć scenariusze, w których przerwiesz podróże w czasie, więc lepiej po prostu umieścić wszystkie stany (w tym stan pola wyboru) w Reduksie, aż wystąpi problem z wydajnością.
kumar303