Dieser Beitrag ist eine kurze Einführung in eine Möglichkeit, Ihren Gutenberg-Code mithilfe von React-Hooks auf dem neuesten Stand zu halten. Wir werden sehen, wie dies von Vorteil ist, warum wir es tun sollten und wie.
Hä, Haken?
Ich nehme an, Sie haben bereits Erfahrung mit etwas komplexeren Gutenberg-Blöcken oder Plugins, die Posts abfragen oder Post-Meta abrufen und aktualisieren. Und daher mit [withSelect](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#withSelect)
und/oder gearbeitet [withDispatch](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#withDispatch)
. Dies sind Komponenten höherer Ordnung in WordPress, die es Ihnen ermöglichen, auf die Stores von WordPress zuzugreifen, um Informationen abzurufen oder zu pushen, die etwas außerhalb der „normalen” Block- oder Post-Bearbeitung liegen. Möglicherweise mussten Sie sie auch verwenden compose
, um Ihre zu kombinieren Komponente mit mehreren Komponenten höherer Ordnung. Wenn Ihr Code diese Muster verwendet, machen Sie sich keine Sorgen – sie funktionieren einwandfrei und werden weiterhin funktionieren! Aber mit fortschreitender Technologie können wir es besser machen.
Anfang 2019 hat React Hooks (Version 16.8) eingeführt, mit denen Sie den Zustand ohne Verwendung einer Klasse verwenden und andere Funktionen verbessern können, was einen besser lesbaren und wiederverwendbaren Code ergibt. Zum Beispiel entfällt die Notwendigkeit, Ihren Code in Komponenten höherer Ordnung zu verpacken, um auf Registrierungen zuzugreifen. Und im Sommer 2019 folgte WordPress und startete benutzerdefinierte Hooks: [useDispatch](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#useDispatch)
und [useSelect](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-data/#useSelect)
.
Die Vorteile von Haken sind vielfältig. Das häufigste Beispiel ist die Verwendung des Komponentenzustands, ohne eine Javascript-Klasse (useState
) schreiben zu müssen. Aber meiner Meinung nach ist der größte Vorteil die Wiederverwendbarkeit. Indem die Notwendigkeit entfällt, Muster wie Render-Requisiten und Komponenten höherer Ordnung zu verwenden, können die Komponenten in weitaus unabhängigere Teile geschrieben werden. Ein weiterer Vorteil von Hooks ist, dass Ihr Code leichter lesbar und verständlicher wird!
Lassen Sie uns direkt zu einigen Beispielen springen und sehen, wie wir unseren Code implementieren useSelect
und useDispatch
einhaken!
ImplementierenuseSelect
Beginnen wir mit withSelect
und dem entsprechenden Hook useSelect
. Diese werden verwendet, um vom Zustand abgeleitete Requisiten von registrierten Selektoren zu erhalten. Übliche Beispiele sind der Zugriff auf die Selektoren „ core
” oder „ core/editor
“, um Abfragen für Beiträge durchzuführen (getEntityRecords
), auf Beitragsmeta zuzugreifen (getEditedPostAttribute
) oder einfach den aktuellen Beitragstyp oder andere Informationen abzurufen.
Zu Demonstrationszwecken beginne ich mit einem einfachen Beispiel. Angenommen, ich habe eine Blockkomponente, in der ich irgendwo einen Postselektor habe. Um Post-Optionen zu füllen, muss ich auf die Registrierung zugreifen ‘ core
‘ und einen GetEntityRecords()
Aufruf durchführen.
Alte Weise verwendenwithSelect
Wenn ich Posts in einem Block abfragen möchte, müsste ich meine Komponente in withSelect
. Dies geschieht üblicherweise in der export
Erklärung.
Bitte beachten Sie, dass dieses Codebeispiel als echter Funktionsblock oder JS-Plugin nicht vollständig ist, es wurde entfernt, um nur die Kernkonzepte von zu zeigen withSelect
. Wenn Sie nach praktischen Codebeispielen suchen, habe ich andere Artikel, die dies behandeln: zB wie man Blöcke mit einem Post-Select implementiert oder wie man Post-Meta zum Inspector hinzufügt. Diese werden mit withSelect
und geschrieben withDispatch
, ebenso wie diese, und kommen Sie dann hierher zurück, um zu lernen, wie man sie in Hooks umwandelt.
const { withSelect } = wp.data;
const AWP_Example_Plugin = ({ somePosts }) => {
console.log("Posts from withSelect = ", somePosts);
return(
<div>
...
</div>
);
}
export default withSelect( (select) => {
return {
somePosts: select( 'core' ).getEntityRecords( 'postType', 'page' ),
};
}) (AWP_Example_Plugin );
Wie Sie in der Zeile sehen können, #12-16
wickle ich meine Komponente mit ein withSelect
. Innerhalb der withSelect-Funktion kann ich auf den gewünschten Store zugreifen und eine Post-Abfrage in der Requisite „ somePosts
” zurückgeben. Diese Requisite ist dann in meiner AWP_Example_Plugin
Komponente verfügbar (wie Sie sehen können, destrukturiere ich somePosts
die Requisiten in Zeile #3
).
Wie bereits erwähnt, funktioniert diese Methode einwandfrei – und wird dies auch weiterhin tun. Aber es gibt mehrere Nachteile mit diesem. Zum einen ist dies nicht ganz einfach zu verstehen. Sicher, das war ein sehr einfaches Beispiel. Auf den ersten Blick auf das Bauteil selbst ist man sich nicht sicher, woher die Requisite somePosts
kommt oder was es ist. Sie müssten wissen, wie Sie nach der export-Anweisung suchen und sehen, ob Wrapper vorhanden sind. Es fühlt sich auch etwas zusammenhanglos an. Sie erledigen einen Großteil der wichtigen Arbeit außerhalb Ihrer Komponente für etwas, das Sie tatsächlich in Ihrer Komponente verfügbar haben möchten.
Machen wir es besser mit Hooks.
Umwandlung inuseSelect
Das Konvertieren von a withSelect
in useSelect
ist so einfach wie es nur geht. Der erste Schritt besteht darin, dass wir die Variable somePosts
innerhalb unserer Komponente definieren können, anstatt außerhalb durch die export
Anweisung. Der zweite Schritt besteht darin, die gesamte Funktion, die wir in hatten, in withSelect
zu verschieben useSelect
. Und das ist es.
const { useSelect } = wp.data;
const AWP_Example_Plugin =() => {
const { somePosts } = useSelect( (select) => {
return {
somePosts: select( 'core' ).getEntityRecords( 'postType', 'page' ),
};
} );
console.log("Posts from useSelect = ", somePosts);
return(
<div>
...
</div>
);
}
export default AWP_Example_Plugin;
Der obige Code liefert genau das gleiche Ergebnis wie der mit withSelect
. Der Unterschied ist, dass der Code jetzt viel verständlicher ist! Wir können jetzt sehr leicht erkennen, dass die Variable somePosts
das Ergebnis einer Post-Abfrage direkt in unserer Komponente speichert.
Wichtiger Hinweis: useSelect
Akzeptiert einen zweiten Parameter; eine Reihe von Abhängigkeiten. Die Abhängigkeiten sind Variablen, die sicherstellen, dass wir nur ausgeführt werden, useSelect
wenn sich eine der Abhängigkeiten (Variablenwerte) geändert hat. Dieser Teil ist wichtiger als hier, daher werde ich diesen Teil im folgenden Abschnitt useDispatch
näher erläutern .useDispatch
ImplementierenuseDispatch
Schauen wir uns nun withDispatch
und den entsprechenden Hook an useDispatch
. Sie werden verwendet, um Requisiten an Registrierungen zu senden. Zum Beispiel Gutenberg sagen, dass er ein Post-Meta über „ core/editor
” aktualisieren soll.
Auch hier sind meine Codebeispiele zu Demonstrationszwecken keine vollständigen funktionalen Codeteile – sie veranschaulichen nur die Teile, die diese Muster betreffen. In diesem Beispiel gehe ich davon aus, dass ich ein Textfeld habe, das ein Post-Meta anzeigt – und ich möchte den Post-Meta-Wert bei Änderung aktualisieren.
Alte Weise verwendenwithDispatch
Da withDispatch
es sich um eine Komponente höherer Ordnung handelt, müsste ich meine Komponente darin einwickeln. Dies geschieht üblicherweise in der export
Erklärung. Um das Textfeld für unsere Metaarbeit zu erstellen, haben wir
Zum Beispiel:
const { withDispatch } = wp.data;
const { __ } = wp.i18n;
const { PluginDocumentSettingPanel } = wp.editPost;
const { TextControl, PanelRow } = wp.components;
const AWP_Example_Plugin = ({ setPostMeta }) => {
return(
<PluginDocumentSettingPanel title={ __( 'withDispatch Example', 'txtdomain') }>
<PanelRow>
<TextControl
label={ __( 'Example post meta', 'txtdomain') }
value=""
onChange={ (value) => setPostMeta( { example_post_meta: value }) }
/>
</PanelRow>
</PluginDocumentSettingPanel>
);
}
export default withDispatch( (dispatch) => {
return {
setPostMeta( newMeta) {
dispatch( 'core/editor' ).editPost( { meta: newMeta } );
}
};
} )( AWP_Example_Plugin );
In Zeile #20-26
packen wir die Komponente in withDispatch
, in der wir eine Funktion „ setPostMeta
” zurückgeben, die Post-Meta versendet (um sie zu aktualisieren). In Zeile #6
destrukturieren wir die Prop, damit wir sie im onChange
Ereignis des Textfelds in Zeile verwenden können #13
. (Bitte beachten Sie, dass das obige Beispiel nicht funktionieren würde, da wir den Wert des Textfelds auf eine leere Zeichenfolge setzen. Dies soll nur zeigen, wie wir den Versand verwenden würden).
Wieder sehen wir, dass der Code nicht so einfach zu verstehen ist. Sie müssten wissen, wie man nach dem Wrapper sucht, um herauszufinden, was die Requisite „ setPostMeta
” ist oder woher sie stammt. Machen wir es besser mit Hooks!
Umwandlung inuseDispatch
Der Wechsel withDispatch
in useDispatch
ist nicht ganz so einfach wie die Umwandlung withSelect
in useSelect
. Es ist aber immer noch ziemlich einfach. Es gibt zwei Dinge zu beachten. Eine davon useDispatch
nimmt einen Geschäftsnamen als ersten Parameter. onChange
Wir würden dann auf den Speicher zugreifen und seine verfügbaren Funktionen aufrufen, wenn wir ihn verwenden (z. B. in einem Ereignis eines Textfelds ). Zweitens ist das Array der Abhängigkeiten zum useDispatch
zweiten Parameter wichtiger als mit useSelect
. Sie riskieren, dass Ihr Code in einer Endlosschleife endet, wenn Sie Abhängigkeiten nicht richtig verwalten. Nur wenn die Abhängigkeitsvariablen geändert werden, wird das Skript erneut ausgeführt useDispatch
.
Zum Beispiel:
const { useDispatch } = wp.data;
const { __ } = wp.i18n;
const { PluginDocumentSettingPanel } = wp.editPost;
const { TextControl, PanelRow } = wp.components;
const AWP_Example_Plugin =() => {
const tmpMetaValue = "";
const { editPost } = useDispatch( 'core/editor', [ tmpMetaValue ] );
return(
<PluginDocumentSettingPanel title={ __( 'useDispatch Example', 'txtdomain') }>
<PanelRow>
<TextControl
label={ __( 'Example post meta', 'txtdomain') }
value={ tmpMetaValue }
onChange={ (value) => editPost( { meta: { example_post_meta: value } }) }
/>
</PanelRow>
</PluginDocumentSettingPanel>
);
}
export default AWP_Example_Plugin;
An der Linie #8
destrukturieren wir, was wir aus dem Laden brauchen core/editor
. Uns interessiert nur die editPost
Funktion, mit der wir Post-Meta aktualisieren können. Als zweiten Parameter useDispatch
geben wir Abhängigkeiten an. Als Beispiel für das Aktualisieren von Post-Meta wäre die Verwendung des Werts des Post-Meta (durch Verwendung von useSelect
) perfekt als Abhängigkeit. In diesem Beispiel habe ich es nur als Dummy-Variable gesetzt. Suchen Sie weiter unten nach einem vollständigeren und realistischeren Beispiel. Und dann rufen wir in der Zeile #16
im Ereignis des Textfelds auf, um das Meta zu aktualisieren. Beachten Sie den Unterschied in dieser Zeile mit oben! Da wir direkt anstelle der Rückgabe eine Funktion verwenden, um Post-Meta für uns zu aktualisieren (), müssen wir ein Objekt mit bereitstellenonChange``editPost``withDispatch``editPost``setPostMeta``meta
als Schlüssel und dann ein Objekt mit dem Post-Meta, das wir aktualisieren möchten. Wir haben den withDispatch
Code in Stücke geteilt.
Dennoch useDispatch
macht die Verwendung den Code viel lesbarer und verständlicher. Außerhalb unserer Komponente wird kein Code mehr hinzugefügt, den wir innerhalb verwenden müssen.
Ein vollständigeres Beispiel, das die Notwendigkeit von eliminiertcompose
Wenn Sie verwenden, werden Sie wahrscheinlich auch diese Komponente withDispatch
benötigen. withSelect
In den useDispatch
obigen Beispielen für die Konvertierung aktualisieren wir einen Post-Meta-Wert. Aber damit das Textfeld richtig funktioniert (und auch den aktuellen Wert anzeigt), müssten wir auch den Post-Meta-Wert abrufen.
Wenn Sie mehrere Komponenten höherer Ordnung verwenden müssen, die um Ihre Komponente gewickelt sind, würden Sie höchstwahrscheinlich eine weitere Gutenberg-Funktion verwenden. [compose](https://developer.wordpress.org/block-editor/reference-guides/packages/packages-compose/)
. Es ist eine praktische Funktion, mehrere Komponenten höherer Ordnung zu einer Komponente höherer Ordnung zu kombinieren, um die Sie Ihre Komponente wickeln können.
Schauen wir uns ein vollständigeres Beispiel einer Komponente an, die einen Post-Meta-Wert in einem Textfeld abruft und aktualisiert, wenn sich sein Wert ändert. Wir beginnen damit, wie wir mit withSelect
und withDispatch
(und damit auch compose
) vorgehen müssten.
Mit withSelect
, withDispatch
undcompose
const { __ } = wp.i18n;
const { compose } = wp.compose;
const { withSelect, withDispatch } = wp.data;
const { PluginDocumentSettingPanel } = wp.editPost;
const { TextControl, PanelRow } = wp.components;
const AWP_Example_Plugin = ({ postMeta, setPostMeta }) => {
return(
<PluginDocumentSettingPanel title={ __( 'withSelect and withDispatch Example', 'txtdomain') }>
<PanelRow>
<TextControl
label={ __( 'Example post meta', 'txtdomain') }
value={ postMeta.example_post_meta }
onChange={ (value) => setPostMeta( { example_post_meta: value }) }
/>
</PanelRow>
</PluginDocumentSettingPanel>
);
}
export default compose( [
withSelect( (select) => {
return {
postMeta: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
};
} ),
withDispatch( (dispatch) => {
return {
setPostMeta( newMeta) {
dispatch( 'core/editor' ).editPost( { meta: newMeta } );
}
};
}) ] )( AWP_Example_Plugin );
Bei line #21-34
setzen wir sie zusammen withSelect
und withDispatch
wickeln sie um unser Bauteil. postMeta
from withSelect
und setPostMeta
from withDispatch
sind jetzt in unserer Komponente als Requisiten verfügbar. Wir destrukturieren sie in line #7
und verwenden sie in #13
und #14
.
Wie Sie sehen können, ist der notwendige Code außerhalb unserer Komponente länger als die Komponente selbst. Ich weiß nicht, wie es euch geht, aber für mich fühlt es sich ein bisschen unzusammenhängend an. Entwickler beginnen möglicherweise, diesen Code von oben zu lesen, ohne den unteren Teil zu sehen, und beginnen sich zu fragen, woher postMeta
und woher setPostMeta
sie kommen – sie scheinen magisch verfügbar zu sein. Für mich ist das sehr unintuitiv.
Schauen wir uns an, wie wir das obige Beispiel in Hooks umwandeln würden.
Verwenden von useSelect
unduseDispatch
const { __ } = wp.i18n;
const { useSelect, useDispatch } = wp.data;
const { PluginDocumentSettingPanel } = wp.editPost;
const { TextControl, PanelRow } = wp.components;
const AWP_Example_Plugin = () => {
const { postMeta } = useSelect( (select) => {
return {
postMeta: select( 'core/editor' ).getEditedPostAttribute( 'meta' ),
};
} );
const { editPost } = useDispatch( 'core/editor', [ postMeta.example_post_meta ] );
return(
<PluginDocumentSettingPanel title={ __( 'useSelect and useDispatch Example', 'txtdomain') }>
<PanelRow>
<TextControl
label={ __( 'Example post meta', 'txtdomain') }
value={ postMeta.example_post_meta }
onChange={ (value) => editPost( { meta: { example_post_meta: value } }) }
/>
</PanelRow>
</PluginDocumentSettingPanel>
);
}
export default AWP_Example_Plugin;
Wie schön und lesbar ist das denn?! Wir können in unserer Komponente sofort sehen, woher postMeta
geholt wird und wie wir Zugriff auf bekommen editPost
. Unsere Komponente ist auch viel einfacher wiederzuverwenden.
Beachten Sie, dass wir in useDispatch
at line #12
das Postmeta hinzufügen, das wir als Abhängigkeit (postMeta.example_post_meta
) aktualisieren. Wenn Sie in dieser Komponente mehrere Post-Meta-Variablen auf dem neuesten Stand halten würden, müssten Sie jede als Abhängigkeit hinzufügen, um sicherzustellen, dass der Versand ausgeführt wird (und tatsächlich das Post-Meta gespeichert wird), wenn sich der Wert einer von ihnen ändert.
Ich hoffe, dies war informativ und hilfreich für jemanden da draußen. Ich bin immer noch ein bisschen ungewohnt mit Haken, aber da ich die Vorteile ihrer Verwendung sehe, kehre ich nicht um!