Gutenberg: Uppdatering med Select och withDispatch till React Hooks (useSelect och useDispatch)
Det här inlägget är en snabb introduktion till ett sätt att hålla din Gutenberg-kod upp till nuvarande standarder genom att använda React-krokar. Vi får se hur detta är fördelaktigt, varför vi bör göra det och hur.
Va, krokar?
Jag antar att du redan har viss erfarenhet av att arbeta med lite mer komplexa Gutenberg-block eller plugins som frågar efter inlägg, eller hämtar och uppdaterar postmeta. Och därmed arbetat med [withSelect](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#withSelect)
och/eller [withDispatch](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#withDispatch)
. Det här är komponenter av högre ordning i WordPress som låter dig komma åt WordPresss butiker för att hämta eller pusha information som ligger lite utanför "normalt" block eller postredigering. Du har möjligen också tvingats använda compose
för att kombinera din komponent med flera komponenter av högre ordning. Om din kod använder dessa mönster, oroa dig inte – de fungerar perfekt och kommer att fortsätta att fungera! Men allt eftersom tekniken utvecklats kan vi göra det bättre.
Tidigt under 2019 lanserade React hooks (version 16.8) – som låter dig använda tillstånd utan att använda en klass och förbättrar andra funktioner som ger mer läsbar och återanvändbar kod. Till exempel att ta bort behovet av att linda in din kod i komponenter av högre ordning för att komma åt register. Och sommaren 2019 följde WordPress och lanserade anpassade krokar: [useDispatch](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#useDispatch)
och [useSelect](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#useSelect)
.
Fördelarna med krokar är många. Det vanligaste exemplet är att tillåta att använda komponenttillstånd utan att behöva skriva en Javascript-klass (useState
). Men enligt mig är den största fördelen återanvändbarhet. Genom att ta bort behovet av att använda mönster som renderingsrekvisita och komponenter av högre ordning kan komponenterna skrivas till mycket mer oberoende bitar. En annan fördel med krokar är att det gör din kod lättare att läsa och förstå!
Låt oss hoppa direkt in i några exempel och se hur vi implementerar useSelect
och useDispatch
krokar i vår kod!
GenomförandeuseSelect
Låt oss börja med withSelect
och dess motsvarande krok useSelect
. Dessa används för att få statligt härledda rekvisita från registrerade väljare. Vanliga exempel är att komma åt " core
‘ eller ‘ core/editor
‘ väljare för att utföra frågor om inlägg (getEntityRecords
), komma åt inläggsmeta (getEditedPostAttribute
) eller helt enkelt få aktuell inläggstyp eller annan information.
I demonstrationssyfte börjar jag med ett enkelt exempel. Anta att jag har en blockkomponent där jag har en postväljare någonstans. För att fylla i inläggsval måste jag komma åt registret ‘ core
‘ och GetEntityRecords()
ringa.
Gammalt sätt att användawithSelect
Om jag vill fråga inlägg i ett block skulle jag behöva slå in min komponent i withSelect
. Detta görs vanligtvis i export
uttalandet.
Observera att det här kodexemplet inte är komplett som ett riktigt funktionsblock eller JS-plugin, det har tagits bort för att bara visa kärnkoncepten för withSelect
. Om du letar efter praktiska kodexempel har jag andra artiklar som täcker detta: t.ex. hur man implementerar block med en post select, eller hur man lägger till post meta till inspektören. De är skrivna med withSelect
och withDispatch
, det gör de också, och kom sedan tillbaka hit för att lära dig hur du omvandlar dem till krokar.
Som du kan se i rad #12-16
lindar jag in min komponent med withSelect
. Inuti withSelect-funktionen kan jag komma åt den butik jag vill ha, och jag returnerar en inläggsfråga i rekvisiten " somePosts
". Denna rekvisita kommer då att finnas tillgänglig i min AWP_Example_Plugin
komponent (som du kan se destrukturerar jag somePosts
från rekvisitan på rad #3
).
Som nämnts tidigare fungerar den här metoden bra – och kommer att fortsätta att göra det. Men det finns flera nackdelar med detta. En är att detta inte är särskilt lätt att förstå. Visst, detta var ett väldigt enkelt exempel. Vid första anblicken på själva komponenten är du inte säker på var rekvisitan somePosts
kommer ifrån eller vad den är. Du måste veta för att leta efter exportförklaringen och se om det finns några omslag. Det känns också lite osammanhängande. Du gör en stor del av viktigt arbete utanför din komponent, för något som du faktiskt vill ha tillgängligt i din komponent.
Låt oss göra det bättre med krokar.
Konverterar tilluseSelect
Att konvertera en withSelect
till useSelect
är hur enkelt som helst. Det första steget är att vi kan definiera variabeln somePosts
inuti vår komponent, snarare än på utsidan av export
påståendet. Det andra steget är att flytta hela funktionen vi hade in withSelect
till useSelect
. Och det är allt.
Ovanstående kod ger exakt samma resultat som den med withSelect
. Skillnaden är att koden nu är mycket mer begriplig! Vi kan nu mycket enkelt se att variabeln somePosts
lagrar resultatet av en inläggsfråga, precis inuti vår komponent.
Viktig anmärkning: useSelect
accepterar en andra parameter; en rad beroenden. Beroendena är variabler som ser till att vi bara kör useSelect
när ett av beroendena (variabelvärdena) har ändrats. Den här biten är viktigare useDispatch
än här, så jag kommer att förklara den här biten ytterligare i useDispatch
avsnittet nedan.
GenomförandeuseDispatch
Låt oss nu titta på withDispatch
och dess motsvarande krok useDispatch
. De används för att skicka rekvisita till register. Till exempel att säga till Gutenberg att uppdatera ett inläggs meta via ‘ core/editor
‘.
Återigen, i demonstrationssyfte är mina kodexempel inte kompletta funktionella kodbitar – de illustrerar bara delarna som rör dessa mönster. I det här exemplet antar jag att jag har ett textfält som visar en postmeta – och jag vill uppdatera postmetavärdet vid förändring.
Gammalt sätt att användawithDispatch
Eftersom withDispatch
det är en komponent av högre ordning, skulle jag behöva linda in min komponent i denna. Detta görs vanligtvis i export
uttalandet. För att få textfältet för vår meta att fungera vi
Till exempel:
På raden #20-26
lindar vi komponenten inuti withDispatch
, där vi returnerar en funktion " setPostMeta
" som skickar post-meta (för att uppdatera den). På line #6
destrukturerar vi rekvisitan så att vi kan använda den i textfältets onChange
händelse vid rad #13
. (Observera att exemplet ovan inte skulle fungera eftersom vi ställer in värdet på textfältet till en tom sträng. Detta är bara för att visa hur vi skulle använda dispatch).
Återigen kan vi se att koden inte är lika enkel att förstå. Du måste veta att leta efter omslaget för att ta reda på vad rekvisitan " setPostMeta
" är eller kommer ifrån. Låt oss göra det bättre med krokar!
Konverterar tilluseDispatch
Att byta withDispatch
till useDispatch
är inte riktigt lika enkelt som det är att konvertera withSelect
till useSelect
. Det är ändå ganska lätt. Det finns två saker att tänka på. En är som useDispatch
tar ett butiksnamn som första parameter. Vi skulle då komma åt butiken och anropa dess tillgängliga funktioner när vi använder den (t.ex. i ett textfälts onChange
händelse). För det andra är uppsättningen av beroenden till den useDispatch
andra parametern viktigare än med useSelect
. Du kan riskera att din kod hamnar i en forever loop om du inte hanterar beroenden korrekt. Först när beroendevariablerna ändras kommer skriptet att köras igen useDispatch
.
Till exempel:
På line #8
destrukturerar vi det vi behöver från butiken ‘ core/editor
‘. Vi är bara intresserade av editPost
funktionen som vi kan använda för att uppdatera postmeta. Som andra parameter useDispatch
tillhandahåller vi beroenden. När det gäller ett exempel på uppdatering av post-meta, skulle användning av värdet på post-meta (genom att använda useSelect
) vara perfekt som beroende. I det här exemplet har jag precis satt den som en dummyvariabel. Titta längre ner för ett mer komplett och realistiskt exempel. Och sedan vid raden #16
i textfältets onChange
händelse ringer vi för editPost
att uppdatera metan. Observera skillnaden i denna linje med att använda withDispatch
ovan! Eftersom vi använder editPost
direkt istället för att returnera en funktion för att uppdatera postmeta för oss (setPostMeta
), måste vi tillhandahålla ett objekt medmeta
som nyckel och sedan ett objekt med postmeta vi vill uppdatera. Vi har typ delat upp withDispatch
koden i bitar.
Ändå useDispatch
gör användningen av koden mycket mer läsbar och begriplig. Ingen mer kod lagt till utanför vår komponent som vi behöver använda inuti.
Ett mer komplett exempel och eliminerar behovet avcompose
Chansen är stor att om du använder withDispatch
, kommer du att behöva withSelect
i den komponenten också. I exemplen för konvertering till useDispatch
ovan uppdaterar vi ett postmetavärde. Men för att textfältet ska fungera korrekt (och även visa det aktuella värdet) skulle vi också behöva hämta postmetavärdet.
Om du behöver använda flera komponenter av högre ordning lindade runt din komponent, skulle du sannolikt använda ännu en Gutenberg-funktion; [compose](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-compose/)
. Det är en praktisk funktion att kombinera flera komponenter av högre ordning till en komponent av högre ordning som du kan slå om din komponent.
Låt oss titta på ett mer komplett exempel på en komponent som hämtar ett postmetavärde i ett textfält och uppdaterar när dess värde ändras. Vi börjar med hur vi skulle behöva gå tillväga med withSelect
och withDispatch
(och därmed också compose
).
Använder och withSelect
_withDispatch``compose
På line #21-34
komponerar vi withSelect
och withDispatch
lindar dem runt vår komponent. postMeta
från withSelect
och setPostMeta
från withDispatch
finns nu i vår komponent som rekvisita. Vi destrukturerar dem på linje #7
och använder dem i #13
och #14
.
Som du kan se är den nödvändiga koden utanför vår komponent längre än själva komponenten. Jag vet inte med dig, men för mig känns det lite osammanhängande. Utvecklare kan börja läsa den här koden från toppen, inte se den nedre delen, och börja undra var postMeta
och setPostMeta
kommer ifrån – de verkar vara magiskt tillgängliga. För mig är detta väldigt ointuitivt.
Låt oss titta på hur vi skulle konvertera ovanstående exempel till krokar.
Använda useSelect
ochuseDispatch
Hur vackert och läsbart är inte det?! Vi kan direkt i vår komponent se var postMeta
den hämtas ifrån och hur vi får tillgång till editPost
. Vår komponent blev också mycket lättare att återanvända.
Observera att useDispatch
på rad #12
lägger vi till postmeta som vi uppdaterar som beroende (postMeta.example_post_meta
). Om du skulle hålla flera post-metavariabler uppdaterade i den här komponenten, måste du lägga till var och en som ett beroende för att säkerställa att utskicket körs (egentligen sparar post-meta) när värdet på en av dem ändras.
Jag hoppas att detta har varit informativt och till hjälp för någon där ute. Jag är fortfarande lite obekant med krokar, men eftersom jag ser fördelarna med att använda dem vänder jag inte tillbaka!