presentations-och Containerkomponenter

vismut

uppdatering från 2019: jag skrev den här artikeln för länge sedan och mina åsikter har sedan dess utvecklats. I synnerhet föreslår jag inte att du delar upp dina komponenter så här längre. Om du tycker att det är naturligt i din kodbas kan det här mönstret vara praktiskt. Men jag har sett det verkställas utan någon nödvändighet och med nästan dogmatisk glöd alltför många gånger. Den främsta anledningen till att jag tyckte att det var användbart var att det lät mig skilja komplex tillståndslogik från andra aspekter av komponenten. Krokar låt mig göra samma sak utan en godtycklig uppdelning. Denna text lämnas intakt av historiska skäl men tar inte den för allvarligt.

det finns ett enkelt mönster som jag tycker är oerhört användbart när jag skriver React-applikationer. Om du har reagerat ett tag har du förmodligen redan upptäckt det. Den här artikeln förklarar det bra, men jag vill lägga till några fler punkter.

du hittar dina komponenter mycket lättare att återanvända och resonera om du delar upp dem i två kategorier. Jag kallar dem behållare och Presentationskomponenter * men jag hörde också fett och mager, Smart och Dum, Stateful och ren, skärmar och komponenter, etc. Dessa är inte exakt samma, men kärntanken är liknande.

mina presentationskomponenter:

  • är bekymrad över hur saker ser ut.
  • kan innehålla både presentations-och behållarkomponenter** inuti, och har vanligtvis vissa DOM-markeringar och egna stilar.
  • tillåter ofta inneslutning via detta.rekvisita.barn.
  • har inga beroenden på resten av appen, till exempel Flux-åtgärder eller butiker.
  • ange inte hur data laddas eller muteras.
  • ta emot data och återuppringningar uteslutande via rekvisita.
  • har sällan sin egen stat (när de gör det är det UI-tillstånd snarare än data).
  • skrivs som funktionella komponenter såvida de inte behöver tillstånd, livscykelkrokar eller prestandaoptimeringar.
  • Exempel: Sida, Sidofält, Berättelse, UserInfo, Lista.

mina containerkomponenter:

  • handlar om hur saker fungerar.
  • kan innehålla både presentations-och behållarkomponenter** inuti men har vanligtvis ingen egen DOM-markering förutom vissa inslagningsdiv och har aldrig några stilar.
  • ge data och beteende till presentations-eller andra containerkomponenter.
  • Ring Flux-åtgärder och ge dessa som återuppringning till presentationskomponenterna.
  • är ofta stateful, eftersom de tenderar att fungera som datakällor.
  • genereras vanligtvis med hjälp av högre ordningskomponenter som connect() från React Redux, createContainer() från Relay eller Container.skapa () från Flux Utils, snarare än skrivet för hand.
  • Exempel: Användarsida, FollowersSidebar, StoryContainer, FollowedUserList.

jag lägger dem i olika mappar för att göra denna skillnad tydlig.

fördelar med detta tillvägagångssätt

  • bättre separation av problem. Du förstår din app och ditt användargränssnitt bättre genom att skriva komponenter på detta sätt.
  • bättre återanvändbarhet. Du kan använda samma presentationskomponent med helt olika tillståndskällor och förvandla dem till separata behållarkomponenter som kan återanvändas ytterligare.
  • Presentationskomponenter är i huvudsak din apps “palett”. Du kan lägga dem på en enda sida och låta designern justera alla sina variationer utan att röra appens logik. Du kan köra skärmdump regressionstester på den sidan.
  • detta tvingar dig att extrahera “layoutkomponenter” som sidofält, sida, ContextMenu och använda detta.rekvisita.barn istället för att duplicera samma markering och layout i flera behållarkomponenter.

kom ihåg att komponenter inte behöver avge DOM. De behöver bara ge kompositionsgränser mellan UI-problem.

dra nytta av det.

När ska man införa Behållare?

jag föreslår att du börjar bygga din app med bara presentationskomponenter först. Så småningom kommer du att inse att du passerar för många rekvisita ner mellankomponenterna. När du märker att vissa komponenter inte använder rekvisita de får utan bara vidarebefordra dem och du måste koppla om alla dessa mellanliggande komponenter när barnen behöver mer data, är det en bra tid att introducera några behållarkomponenter. På så sätt kan du få data och beteende rekvisita till bladkomponenterna utan att belasta de orelaterade komponenterna i mitten av trädet.

Detta är en pågående process för refactoring så försök inte att få det rätt första gången. När du experimenterar med detta mönster kommer du att utveckla en intuitiv känsla för när det är dags att extrahera vissa behållare, precis som du vet när det är dags att extrahera en funktion. Min gratis Redux Egghead-serie kan hjälpa dig med det också!

andra dikotomier

det är viktigt att du förstår att skillnaden mellan presentationskomponenterna och behållarna inte är teknisk. Snarare är det en skillnad i deras syfte.

däremot är här några relaterade (men olika!) tekniska skillnader:

  • statslös och statslös. Vissa komponenter använder React setState () – metoden och vissa gör det inte. medan behållarkomponenter tenderar att vara stateful och presentationskomponenter tenderar att vara statslösa, är detta inte en hård regel. Presentationskomponenter kan vara stateful, och behållare kan vara statslösa också.
  • klasser och funktioner. Sedan React 0.14 kan komponenter deklareras både som klasser och som funktioner. Funktionella komponenter är enklare att definiera men de saknar vissa funktioner som för närvarande endast är tillgängliga för klasskomponenter. Vissa av dessa begränsningar kan försvinna i framtiden men de finns idag. Eftersom funktionella komponenter är lättare att förstå föreslår jag att du använder dem om du inte behöver tillstånd, livscykelkrokar eller prestandaoptimeringar, som endast är tillgängliga för klasskomponenterna just nu.
  • ren och Oren. Folk säger att en komponent är ren om det garanteras att returnera samma resultat med samma rekvisita och tillstånd. Rena komponenter kan definieras både som klasser och funktioner, och kan vara både statliga och statslösa. En annan viktig aspekt av rena komponenter är att de inte litar på djupa mutationer i rekvisita eller tillstånd, så deras renderingsprestanda kan optimeras genom en grund jämförelse i deras shouldComponentUpdate() krok. För närvarande kan endast klasser definiera shouldComponentUpdate() men det kan förändras i framtiden.

både presentationskomponenter och behållare kan falla i någon av dessa hinkar. Enligt min erfarenhet tenderar presentationskomponenter att vara statslösa rena funktioner, och behållare tenderar att vara statliga rena klasser. Men det här är inte en regel utan en observation, och jag har sett exakt motsatta fall som var vettiga under specifika omständigheter.

ta inte presentations-och behållarkomponentseparationen som en dogma. Ibland spelar det ingen roll eller det är svårt att dra gränsen. Om du känner dig osäker på om en specifik komponent ska vara presentations-eller en behållare kan det vara för tidigt att bestämma. Svettas inte!

exempel

denna gist av Michael Chan spikar det ganska mycket.

Vidare läsning

  • komma igång med Redux
  • Mixins är döda, Länge leve komposition
  • Containerkomponenter
  • Atomic webbdesign
  • bygga Facebook News Feed med relä

fotnoter

* i en tidigare version av den här artikeln kallade jag dem “smarta” och “dumma” komponenter men det var alltför hårt för presentationskomponenterna och, viktigast av allt, förklarade inte riktigt skillnaden i deras syfte. Jag tycker om de nya villkoren mycket bättre, och jag hoppas att du också gör det!

* * i en tidigare version av denna artikel hävdade jag att presentationskomponenter endast bör innehålla andra presentationskomponenter. Jag tror inte längre att så är fallet. Huruvida en komponent är en presentationskomponent eller en behållare är dess implementeringsdetalj. Du bör kunna ersätta en presentationskomponent med en behållare utan att ändra någon av samtalsplatserna. Därför kan både presentations-och behållarkomponenter innehålla andra presentations-eller behållarkomponenter bara bra.

Lämna ett svar

Din e-postadress kommer inte publiceras.