Przekazywanie stanu sklepu jako właściwości, czy każdy komponent uzyskujący dostęp do sklepów globalnych?

Jestem nieco zdezorientowany stwierdzeniami: "Renders the whole application" I "Passing state to child components".

Przykład 1:

Mam aplikację todos z AppComponent i TodosListComponent. AppComponent chwyta tablicę todos ze sklepu i przekazuje ją jako właściwość TodosListComponent.

Przykład 2:

Mam ogromną aplikację z wieloma stanami. Mam około 50 komponentów budujących moją aplikację. Czy chcę przejść cały stan ze sklepów z AppComponent przez wszystkie 50 składniki?

Więc zastanawiam się, co to jest konwencja? Bardziej sensowne jest dla mnie, aby poszczególne komponenty słuchały bezpośrednio sklepów, na których im zależy. Zaletą jest to, że tylko poszczególne komponenty rerender, ale dlaczego wtedy pojęcie "cały rerender aplikacji na zmianę stanu"?

Jakie są plusy i minusy każdego z nich? Na czym polega wspólna konwencja?

Author: FakeRainBrigand, 2014-10-25

2 answers

Możesz sobie z tym poradzić na kilka sposobów. Myślę, że wszystkie są ważne i mają swoje kompromisy.

Zdobądź cały stan i przekaż go dzieciom]} To jest technika, o którą prosiłeś. Korzystając z tej metody, będziesz mieć jakąś funkcję lub metodę dostępną dla komponentu najwyższego poziomu, który zamienia wszystkie dane ze sklepów w "big bag of state", a następnie będziesz selektywnie przekazywać fragmenty tych danych do komponentów potomnych. Jeśli te elementy mają swoje własne dzieci, przekażą je w razie potrzeby.

Zaletą tej metody jest to, że ogólnie ułatwia debugowanie. Jeśli musisz zmienić sposób, w jaki fragment stanu jest pobierany ze sklepu, musisz tylko zmienić go w komponencie najwyższego poziomu-tak długo, jak zostanie przekazany o tej samej nazwie, pozostałe komponenty będą "po prostu działać."Jeśli jakiś fragment danych jest błędny, wystarczy spojrzeć w jednym miejscu, aby dowiedzieć się, dlaczego.

Minusem tej techniki co ja call "props explosion" -możesz skończyć mijając lot właściwości wokół. Używam tej metody w średniej wielkości aplikacji flux, a fragment komponentu aplikacji najwyższego poziomu wygląda tak:

<section id="col-left">
  <Filters loading={this.state.loading}
            events={this.state.events}
            playbackRate={this.state.videoPlayback.playbackRate}
            autoPlayAudio={this.state.audioPlayback.autoPlay}
            role={this.state.role} />
</section>

<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
  <SessionVideo videoUuid={this.state.session.recording_uuid}
                lowQualityVideo={this.state.session.low_quality_video_exists}
                playbackRate={this.state.videoPlayback.playbackRate} />
  <section id="transcript">
    <Transcript loading={this.state.loading}
                events={this.state.events}
                currentEvents={this.state.currentEvents}
                selection={this.state.selection}
                users={this.state.session.enrolled_users}
                confirmedHcs={this.state.ui.confirmedHcs}

                currentTime={this.state.videoPlayback.position}
                playing={this.state.videoPlayback.playing} />
  </section>
</section>

W szczególności, może istnieć wiele komponentów między najwyższym poziomem a jakimś ewentualnym dzieckiem, które nic nie robią z danymi, z wyjątkiem przekazywania ich dalej, ściślej łącząc te komponenty z ich pozycją w hierarchii.

Ogólnie podoba mi się debuggability ta technika zapewnia, choć jako aplikacja stała się większa i bardziej złożona stwierdziłem, że nie było pomysłem, aby to zrobić tylko z jednym komponentem najwyższego poziomu.

Pobierz cały stan i przekaż go jako jeden obiekt

Jeden z twórców Facebook wspomniał o tej technice. Tutaj dostaniesz wielki worek stanu, tak jak wyżej, ale przekażesz całość (lub całe jego podsekcje), a nie poszczególne właściwości. Wykorzystując React.PropTypes.shape w komponentach potomnych, można upewnij się, że odpowiednie właściwości są przekazywane.

Plusem jest to, że przekazujesz o wiele mniej właściwości; powyższy przykład może wyglądać bardziej Tak:

<section id="col-left">
  <Filters state={this.state} />
</section>

<section id="col-center" className={leftPaneActive ? "" : "inactive"}>
  <SessionVideo session={this.state.session}
                playback={this.state.videoPlayback} />
  <section id="transcript">
    <Transcript state={this.state} />
  </section>
</section>

Minusem jest to, że trochę trudniej jest radzić sobie ze zmianami w kształcie stanu; zamiast zmieniać komponent najwyższego poziomu, będziesz musiał wyśledzić wszędzie, gdzie dany fragment danych jest używany I zmienić sposób, w jaki komponent uzyskuje dostęp do właściwości. Również, shouldComponentUpdate może potencjalnie stać się trochę trudniejsze do wdrożenia.

Zezwalaj komponentom na uzyskanie własnego stanu

Na drugim końcu spektrum, możesz przyznać komponenty potomne specyficzne dla aplikacji (tj. nie nadające się do wielokrotnego użytku), aby uzyskać dostęp do sklepów i zbudować ich własny stan na podstawie zdarzeń zmiany sklepu. Komponenty, które budują swój własny stan w ten sposób, są czasami nazywane "widokami kontrolera" lub, częściej w dzisiejszych czasach, " komponentami kontenera."

Plusem jest oczywiście to, że nie musisz sobie z tym radzić z przekazywaniem właściwości w ogóle (inne niż procedury obsługi zmian i właściwości Dla komponentów wielokrotnego użytku).

Minusem jest jednak to, że Twoje komponenty są bardziej powiązane ze sklepami-zmiana sklepów lub danych, które dostarczają (lub interfejsu, za pomocą którego dostarczają te dane) może zmusić cię do ponownego przeanalizowania kodu dla większej liczby komponentów.

Również, jak wspomniano w komentarzach, może to potencjalnie utrudnić renderowanie serwera. If you only użyj właściwości (zwłaszcza na najwyższym poziomie), możesz je łatwiej przenieść do klienta i ponownie zainicjować Reacta tymi samymi właściwościami. Pozwalając sklepom na określenie własnych danych, musisz w jakiś sposób wstrzyknąć te dane do sklepów, aby umożliwić komponentom uzyskanie tych danych.

Powszechnym podejściem, które zazwyczaj używam obecnie, jest to, aby każdy komponent w Twojej aplikacji polegał tylko na właściwościach dla globalnego stanu aplikacji, a następnie zdecydować, czy ma to większy sens (1) połącz je bezpośrednio z flux, owijając je w kontener, lub (2) pozwól, aby rekwizyty zostały przekazane z jakiegoś macierzystego kontenera.


Istnieją abstrakcje, które możesz wykorzystać, aby niektóre z tych technik były bardziej opłacalne. Na przykład, Facebook dev miał to do powiedzenia w komentarz na temat wiadomości hakerskich :

Teraz wszystkie Twoje dane są w sklepach, ale jak je wprowadzić do konkretnego komponentu, który ich potrzebuje? Zaczęliśmy od dużych komponentów najwyższego poziomu, które wyciągnij wszystkie dane potrzebne dzieciom i przekaż je przez rekwizyty. Prowadzi to do dużej ilości cruft i nieistotnego kodu w komponentach pośrednich. To, na czym zdecydowaliśmy się w większości, to Komponenty deklarujące i pobierające dane, których same potrzebują, z wyjątkiem kilku małych, bardziej ogólnych komponentów. Ponieważ większość naszych danych jest pobierana asynchronicznie i buforowana, stworzyliśmy mixiny, które ułatwiają deklarowanie, jakich danych potrzebuje twój komponent, oraz Podłączanie pobierania i nasłuchiwania aktualizacje metod cyklu życia (componentWillMount, itd.).

 34
Author: Michelle Tilley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-27 17:13:13

Jason Bonta z Facebook wyjaśnił w swojej reakcji pojęcie "kontenerów".js Conf 2015 dyskusja.

Podsumowując: kontenery są po prostu komponentami, które zawijają inne komponenty i zajmują się wszelkimi kwestiami związanymi z danymi, takimi jak rozmowa ze sklepami, podczas gdy komponent bazowy koncentruje się wyłącznie na widoku (znaczniki / style / etc.) i nie obchodzi, skąd pochodzą dane.

To sprawia, że komponent

  • Wysoce wielokrotnego użytku, ponieważ może być owinięty z innym kontenerem, gdy dane muszą pochodzić z innego miejsca,

  • Nie zawierają stanu nieistotnego, dlatego łatwiejsze do wdrożenia i optymalizacji shouldComponentUpdate i

  • Użycie composition zamiast mixins do tego wyrównuje się z co jest prawdopodobnie przyszłością Reacta z ES6, który nie ma idiomatycznych mixins.

 3
Author: Raman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 15:32:16