Czy sklepy utrzymują swój własny stan i mają możliwość wywoływania usług sieciowych i przechowywania danych w ten sposób ... w takim przypadku działania są po prostu głupimi odbiorcami wiadomości,
-LUB-
... czy sklepy powinny być głupimi odbiorcami niezmiennych danych z działań (a akcjami powinny być te, które pobierają / wysyłają dane między źródłami zewnętrznymi? Sklep w tym przypadku działałby jako modele widoków i byłby w stanie agregować / filtrować ich dane przed ustanowieniem własnej bazy stanu na niezmiennych danych, które były zasilane przez działanie.
Wydaje mi się, że powinien to być jeden lub drugi (a nie mieszanka obu). Jeśli tak, dlaczego jeden jest preferowany / zalecany w stosunku do drugiego?
reactjs
reactjs-flux
plaxdan
źródło
źródło
Odpowiedzi:
Widziałem wzorzec strumienia zaimplementowany w obie strony i po zrobieniu obu (początkowo stosując poprzednie podejście) uważam, że sklepy powinny być głupimi odbiorcami danych z akcji, a asynchroniczne przetwarzanie zapisów powinno żyć w twórcy akcji. ( Odczyty asynchroniczne mogą być obsługiwane inaczej ). Z mojego doświadczenia wynika, że ma to kilka zalet, w kolejności od najważniejszych:
Twoje sklepy stają się całkowicie synchroniczne. Dzięki temu logika sklepu jest znacznie łatwiejsza do śledzenia i bardzo łatwa do testowania - wystarczy utworzyć instancję sklepu z określonym stanem, wysłać mu akcję i sprawdzić, czy stan zmienił się zgodnie z oczekiwaniami. Ponadto jedną z podstawowych koncepcji przepływu jest zapobieganie kaskadowym wysyłkom i zapobieganie wielu wysyłkom jednocześnie; Jest to bardzo trudne, gdy Twoje sklepy przetwarzają dane asynchronicznie.
Wszystkie wywołania akcji pochodzą od twórców akcji. Jeśli obsługujesz operacje asynchroniczne w swoich sklepach i chcesz, aby moduły obsługi akcji sklepów były synchroniczne (i powinieneś, aby uzyskać gwarancje przepływu w pojedynczej wysyłce), Twoje sklepy będą musiały uruchomić dodatkowe akcje SUCCESS i FAIL w odpowiedzi na asynchroniczne przetwarzanie. Zamiast tego umieszczenie tych rozkazów w kreatorach akcji pomaga oddzielić zadania twórców akcji od sklepów; co więcej, nie musisz przekopywać się przez logikę sklepu, aby dowiedzieć się, skąd wysyłane są akcje. Typowa asynchroniczna akcja w tym przypadku może wyglądać mniej więcej tak (zmień składnię
dispatch
wywołań na podstawie stylu używanego strumienia):Logika, która w przeciwnym razie mogłaby zostać zduplikowana w różnych działaniach, powinna zostać wyodrębniona do osobnego modułu; w tym przykładzie byłby to moduł
SomeDataAccessLayer
, który obsługuje rzeczywiste żądanie Ajax.Potrzebujesz mniej twórców akcji. To mniej wielka sprawa, ale miło mieć. Jak wspomniano w punkcie 2, jeśli Twoje sklepy mają obsługę wysyłania akcji synchronicznych (a powinny), będziesz musiał uruchomić dodatkowe akcje, aby obsłużyć wyniki operacji asynchronicznych. Wykonywanie poleceń w kreatorze akcji oznacza, że twórca pojedynczej akcji może wywołać wszystkie trzy typy akcji, obsługując sam wynik asynchronicznego dostępu do danych.
źródło
"SOME_ACTION"
), używam API, aby wykonać request (SomeDataAccessLayer.doSomething(userId)
), które zwraca obietnicę, aw obu.then
funkcjach wysyłam dodatkowe akcje. Stan żądania może (mniej więcej) mapować do stanu przechowywania, jeśli aplikacja musi wiedzieć o stanie stanu. Jak ta mapa jest zależna od aplikacji (np. Może każdy komentarz ma indywidualny stan błędu, a la Facebook, a może jest jeden komponent globalnego błędu)Napisałem na Twitterze to pytanie do deweloperów na Facebooku, a odpowiedź, którą otrzymałem od Billa Fishera, brzmiała:
źródło
a call from store works better when action triggers from non-human driver
?Sklepy powinny zrobić wszystko, łącznie z pobieraniem danych i sygnalizowaniem komponentom, że dane sklepu zostały zaktualizowane. Czemu? Ponieważ działania mogą być wtedy lekkie, jednorazowe i wymienne bez wpływu na ważne zachowanie. Wszystkie ważne zachowania i funkcjonalności mają miejsce w sklepie. Zapobiega to również powielaniu zachowań, które w innym przypadku zostałyby skopiowane w dwóch bardzo podobnych, ale różnych akcjach. Sklepy są Twoim singlem źródłem prawdy.
W każdej implementacji Flux, którą widziałem, akcje są w zasadzie łańcuchami zdarzeń zamienianymi w obiekty, tak jak tradycyjnie miałbyś zdarzenie o nazwie „anchor: clicked”, ale we Flux byłoby zdefiniowane jako AnchorActions.Clicked. Są nawet tak „głupi”, że większość implementacji ma oddzielne obiekty Dispatcher, które faktycznie wysyłają zdarzenia do nasłuchujących sklepów.
Osobiście podoba mi się implementacja Flux firmy Reflux, w której nie ma oddzielnych obiektów Dispatcher, a obiekty Action same wykonują wysyłkę.
edit: Facebook Flux faktycznie pobiera w "twórcach akcji", więc używają inteligentnych akcji. Przygotowują również ładunek za pomocą sklepów:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/actions/ChatMessageActionCreators.js#L27 (linia 27 i 28)
Wywołanie zwrotne po zakończeniu wywołałoby tym razem nowe działanie z pobranymi danymi jako ładunkiem:
https://github.com/facebook/flux/blob/19a24975462234ddc583ad740354e115c20b881d/examples/flux-chat/js/utils/ChatWebAPIUtils.js#L51
Więc myślę, że to lepsze rozwiązanie.
źródło
Przedstawię argument za „głupimi” działaniami.
Umieszczając odpowiedzialność za gromadzenie danych widoków w Akcjach, łączysz swoje Akcje z wymaganiami dotyczącymi danych w Twoich widokach.
W przeciwieństwie do tego, Akcje ogólne, które deklaratywnie opisują intencję użytkownika lub zmianę stanu w aplikacji, umożliwiają dowolnemu Sklepowi, który reaguje na tę akcję, przekształcenie intencji w stan dostosowany specjalnie do subskrybowanych widoków.
To nadaje się do większej liczby, ale mniejszych, bardziej wyspecjalizowanych Sklepów. Opowiadam się za tym stylem, ponieważ
Celem Sklepu jest udostępnianie danych do wyświetleń. Nazwa „Działanie” sugeruje mi, że jej celem jest opisanie zmiany w mojej Aplikacji.
Załóżmy, że musisz dodać widżet do istniejącego widoku pulpitu nawigacyjnego, który pokazuje nowe, fantazyjne dane zagregowane, które właśnie wprowadził zespół zaplecza.
W przypadku „inteligentnych” działań może być konieczna zmiana akcji „odśwież-panel informacyjny”, aby korzystać z nowego interfejsu API. Jednak „Odświeżanie dashboardu” w sensie abstrakcyjnym nie uległo zmianie. Zmieniły się wymagania dotyczące danych w Twoich widokach.
Za pomocą „głupich” akcji możesz dodać nowy Sklep do wykorzystania przez nowy widżet i skonfigurować go tak, aby po otrzymaniu typu działania „odśwież-dashboard” wysyłał żądanie nowych danych i pokazywał je nowy widget, gdy będzie gotowy. Wydaje mi się sensowne, że gdy warstwa widoku potrzebuje więcej lub innych danych, rzeczy, które zmieniam, są źródłami tych danych: Sklepy.
źródło
Flux-React -Router-demo firmy Gaeron ma przyjemną odmianę użytkową „prawidłowego” podejścia.
ActionCreator generuje obietnicę z zewnętrznej usługi API, a następnie przekazuje obietnicę i trzy stałe akcji do
dispatchAsync
funkcji w proxy / rozszerzonym Dispatcherze.dispatchAsync
zawsze wyśle pierwszą akcję, np. „GET_EXTERNAL_DATA”, a po zwróceniu obietnicy wyśle „GET_EXTERNAL_DATA_SUCCESS” lub „GET_EXTERNAL_DATA_ERROR”.źródło
Jeśli chcesz pewnego dnia mieć środowisko programistyczne porównywalne z tym, co widzisz w słynnym filmie Bret Victor Inventing on Principle , powinieneś raczej używać głupich sklepów, które są po prostu projekcją działań / zdarzeń wewnątrz struktury danych, bez żadnych skutków ubocznych. Pomogłoby również, gdyby twoje sklepy były faktycznie członkami tej samej globalnej niezmiennej struktury danych, jak w Redux .
Więcej wyjaśnień tutaj: https://stackoverflow.com/a/31388262/82609
źródło