Benutzerdefinierten Gutenberg-Block erstellen – Teil 10: Abrufen von Posts und Komponenten höherer Ordnung
In diesem letzten Teil der Tutorienreihe zu benutzerdefinierten Gutenberg-Blöcken lernen wir, wie man Komponenten höherer Ordnung verwendet, um die Komponenten von WordPress zum Durchführen von Abfragen für Beiträge und andere WordPress-Kerninformationen zu nutzen.
Im vorherigen Teil haben wir etwas über dynamische Blöcke gelernt und schließlich haben wir Funktionen zum Eingeben einer Beitrags-ID und zum Verwenden von PHP zum dynamischen Abrufen des Beitrags und zum Rendern im Frontend- und Vorschaumodus implementiert. Die manuelle Eingabe einer Beitrags-ID ist weder intuitiv noch benutzerfreundlich. Es ist viel besser, dem Benutzer eine Möglichkeit zu bieten, Beiträge anhand des Beitragstitels auszuwählen oder zu suchen und auf etwas zu klicken, um einen auszuwählen.
Ein Teil der Lösung ist ziemlich einfach; wie Sie Beiträge aus der edit
Funktion Ihres Blocks abfragen. Dafür haben wir einige Möglichkeiten, und die beste Option ist die Verwendung einiger der sogenannten Komponenten höherer Ordnung von WordPress. Sie können auch Javascript-Browsermethoden verwenden, um einen AJAX-Aufruf an die WordPress-REST-API auszuführen, indem Sie beispielsweise [fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
oder axios verwenden. WordPress bietet tatsächlich eine eigene Version von fetch
: apiFetch()
.
Der andere Teil der Lösung liegt ein bisschen bei Ihnen; So präsentieren Sie die Liste oder Auswahl in unserem Block. Wie werden Sie die Liste der Posts präsentieren, aus denen Sie auswählen können? In einer Auswahlliste, einer Liste von Kontrollkästchen oder Optionsfeldern? Oder möchten Sie eine Suchfunktion anbieten und damit eine Autocomplete-Lösung oder eine Filterlösung implementieren? Sollen Sie die Auswahl mehrerer Beiträge zulassen oder nur einen? Normalerweise können Sie dies lösen, indem Sie verschiedene WordPress-Komponenten verwenden, aber Sie müssen sich entscheiden, welche Lösung Sie implementieren möchten.
Lassen Sie uns zunächst etwas über Komponenten höherer Ordnung und das WordPress-Datenmodul lernen, bevor wir uns ansehen, wie wir Post-Abfragen in unserem Block durchführen können.
WordPress Core Data-Modul und höherwertige Komponenten
Wenn Sie mit React arbeiten, müssen Sie häufig den Status an untergeordnete Komponenten oder nach oben an eine gemeinsame übergeordnete Komponente weitergeben, damit alle anderen untergeordneten Komponenten darauf zugreifen können. Eine Lösung zur Lösung des Problems der Zentralisierung des Zustands einer Anwendung ist die Verwendung von Redux. Mit Redux können Sie Speicher erstellen – das sind Objekte, die den Status und die Informationen einer Anwendung enthalten.
Das WordPress-Datenmodul ist ein Knotenpunkt verschiedener Stores und bietet Funktionen zum Verwalten von Daten zwischen verschiedenen Modulen. Es baut auf Redux auf – aber verwechseln Sie es nicht mit Redux für WordPress, da es einige Unterschiede gibt. Sie können Ihre eigenen Shops in WordPress registrieren oder, was noch wichtiger ist, auf die registrierten Shops von WordPress zugreifen.
Hier ist eine Übersicht der verfügbaren Stores im WordPress-Datenmodul (wird sich wahrscheinlich im Laufe der Zeit ändern). Alle WordPress-Stores sind im Core Data-Modul enthalten. Zum Beispiel gibt es Speicher, die die Daten des Editors (core/editor
), Hinweise (core/notices
), Blockdaten (core/blocks
), Ansichtsfensterinformationen (core/viewport
) und nicht zuletzt den Hauptspeicher selbst enthalten – core
.
Um auf Daten aus Geschäften zuzugreifen, müssen Sie Selektoren verwenden. WordPress hat einen Selektor innerhalb des wp.data
Pakets; [select](https://developer.wordpress.org/block-editor/packages/packages-data/#select)()
. Sie können die Stores auch mit manipulieren dispatch
, dies wird jedoch nicht von dieser Tutorial-Reihe behandelt. Sie können den Selektor ganz einfach selbst ausprobieren, um zu sehen, was in den WordPress-Shops verfügbar ist.
Selektor ausprobieren
Öffnen Sie den Gutenberg-Editor in Chrome und öffnen Sie das Konsolen-Debugger-Tool. Eintippen:
wp.data.select('core')
Und drücken Sie die Eingabetaste. Sie sollten ein Objekt als Antwort mit allen Selektoren (Funktionen) erhalten, die Sie verwenden können. Als Beispiele finden Sie Funktionen wie getMedia
, getTaxonomy
, getAuthors
, und so weiter. Diejenige, die wir zum Abfragen von Beiträgen verwenden werden, ist ebenfalls vorhanden, hat aber keinen intuitiven Namen; es heißt getEntityRecords
. Im Moment sind einige dieser Funktionen dokumentiert, die meisten leider nicht.
Versuchen Sie auch andere Geschäfte als core
, zum Beispiel:
wp.data.select('core/editor').getBlocks()
Dies gibt alle Informationen zu allen Blöcken zurück, die sich derzeit in Ihrem Beitrag befinden. Sie können damit im Chrome-Konsolen-Debugger herumspielen und versuchen, einige Funktionen aufzurufen, um zu sehen, was Sie als Antwort erhalten. Einige erfordern Parameter und andere nicht.
Um Selektoren verwenden und auf Speicher zugreifen zu können, müssen wir sie innerhalb von Komponenten höherer Ordnung verwenden. Komponenten höherer Ordnung sind einfach ein Muster dafür, etwas in React zu tun. Wir übergeben eine Komponente an eine Funktion (oder Komponente), die einige Requisiten hinzufügen könnte, und geben dann eine neue Komponente zurück.
Im WordPress-Datenmodul finden wir [withSelect](https://developer.wordpress.org/block-editor/packages/packages-data/#withSelect)
; eine Komponente höherer Ordnung, die zum Einfügen von Requisiten mit registrierten Selektoren verwendet werden kann. Mit anderen Worten; innerhalb withSelect
haben wir Zugriff auf den Selektor select()
und können ihn verwenden, um Aufrufe durchzuführen. Die Selektorergebnisse sind Requisiten für die Komponente, an die wir übergeben withSelect
. Wenn Sie mehrere Komponenten höherer Ordnung kombinieren müssen, bietet das WordPress-Datenmodul die compose
Funktion, aber dies würde den Rahmen dieses Tutorials sprengen. Wir werden nur eine Komponente höherer Ordnung verwenden; withSelect
.
Das war viel Theorie, also fangen wir an, uns etwas Code und praktische Beispiele anzusehen.
Abrufen von Beiträgen mit withSelect, select und getEntityRecords
Um das Obige zusammenzufassen, müssen wir die Komponente höherer Ordnung withSelect
für unseren Block einrichten. Darin können wir Selektoren verwenden, um auf die Stores von WordPress zuzugreifen, die Requisiten für die Komponente sind, an die wir übergeben withSelect
. Wir werden den core
Speicher und den Selektor verwenden getEntityRecords
, um Beiträge abzufragen.
Die Funktion getEntityRecords
ist derzeit leider nicht sehr dokumentiert. Aber ich habe gelernt, dass wir postType
als ersten Parameter (entity kind) übergeben können und dann den Posttyp als zweiten Parameter (zB ‘ post
‘ oder ‘ page
‘). Der dritte Parameter ist optional und kann ein Objekt mit Abfrageargumenten sein. Den dritten Parameter sehen wir uns später an.
Wenn Sie dieser Tutorial-Serie aus dem vorherigen Teil gefolgt sind, hätten Sie einen benutzerdefinierten Block, der eine manuell eingegebene Post-ID in einer Texteingabe akzeptiert. Der Block verwendet PHP, um den Beitrag dynamisch im Frontend (und im Vorschaumodus) zu rendern. Lassen Sie uns die Anforderung entfernen, die Post-ID manuell einzugeben, und sie durch etwas intuitiveres ersetzen. Wie bereits erwähnt, müssen Sie selbst entscheiden, wie Sie die Liste der Beiträge präsentieren und den Benutzer am besten einen Beitrag auswählen lassen. Um es einfach zu halten, fügen wir eine Auswahl aller Beitragstitel zur Auswahl hinzu.
Codierung derwithSelect
Beginnen wir mit der Codierung. Zuerst müssen wir das, was wir brauchen, aus dem Datenpaket destrukturieren;
const { withSelect, select } = wp.data;
Dann verwenden wir withSelect
die Funktion unseres Blocks edit
und geben unsere Bearbeitungskomponente weiter; FirstBlockEdit
. Darin withSelect
destrukturieren wir select
als Parameter und verwenden den Selektor select()
, um Beiträge mit abzufragen getEntityRecords
. Wir geben ein Objekt mit einer Eigenschaft zurück, die wir aufrufen und posts
die das Ergebnis des select()
Aufrufs enthält.
...
edit: withSelect(select => {
return {
posts: select('core').getEntityRecords('postType', 'post')
}
})(FirstBlockEdit),
save:() => { return null }
...
Mit dem obigen Code hat unsere Komponente FirstBlockEdit
nun eine neue Stütze; posts
. Alles, was wir innerhalb der withSelect
Komponente höherer Ordnung zurückgeben, ist als Requisiten für die Komponente zugänglich, die wir übergeben (in der Klammer ganz am Ende).
Umgang mit den Beiträgen aus dem Selektor
Wir können jetzt in unsere Komponente gehen FirstBlockEdit
und uns die neue ansehen props.posts
. Da unsere Komponente eine klassenbasierte Komponente ist, müssen wir auf Requisiten mit verweisen this
. render()
Lassen Sie es uns in der Funktion in der Konsole abmelden FirstBlockEdit
:
render() {
const { attributes, setAttributes } = this.props;
console.log(this.props.posts);
...
}
Behalten Sie Ihren Konsolen-Debugger im Auge. Möglicherweise stellen Sie fest, dass dies zweimal protokolliert wird. first null
, und einige Zeit später protokolliert es eine Reihe von Beiträgen. Dies liegt daran, dass das Abfragen von Beiträgen asynchron erfolgt. Unsere Komponente wird zuerst vor der Antwort gerendert, zu diesem Zeitpunkt props.posts
ist null
. Sobald wir eine Antwort erhalten, wird unsere Komponente erneut mit der ausgefüllten Requisite gerendert. Sie sollten immer daran denken, diesen kleinen Zeitraum ohne Daten in Ihrem Code zu berücksichtigen.
Hinzufügen einer Auswahl zum Anzeigen der Beiträge
Bereiten wir uns darauf vor, eine Auswahl mit den zurückgegebenen Beiträgen zu füllen, und dafür verwenden wir die WordPress-Komponente SelectControl
. Die Komponente SelectControl
akzeptiert ein Array von Auswahlmöglichkeiten, wobei jede Auswahlmöglichkeit ein Objekt mit den Eigenschaften value
und ist label
.
Wenn Sie sich die protokollierte (zweite) Antwort der Konsole ansehen, können Sie sehen, dass wir ein Array von Post-Objekten erhalten. Jeder Beitrag enthält die meisten Informationen des Beitrags, aber für die Auswahlmöglichkeiten in einer Auswahl interessieren uns nur die Beitrags-ID als Wert und der Beitragstitel als Label. Also durchlaufen wir die posts
Stütze und füllen eine Array-Variable, die wir weitergeben SelectControl
. Vergessen Sie nicht, den kleinen Zeitrahmen zu berücksichtigen, in dem sich die posts
Requisite befindet null
. In diesem Fall füllen wir das Auswahlarray mit einer Option, die die Bezeichnung „Loading…” trägt.
let choices = [];
if (this.props.posts) {
choices.push({ value: 0, label: __('Select a post', 'awhitepixel') });
this.props.posts.forEach(post => {
choices.push({ value: post.id, label: post.title.rendered });
});
} else {
choices.push({ value: 0, label: __('Loading...', 'awhitepixel') })
}
Beachten Sie, dass wir den Beitragstitel als bezeichnen müssen post.title.rendered
. Sie können selbst in der Konsole protokolliert posts
sehen und sehen, wie die Informationen für jeden Beitrag aufgebaut sind.
Danach müssen wir einfach ein hinzufügen, SelectControl
wo immer wir es wollen. Es kann sich im Block selbst (vorzugsweise im Code für den Bearbeitungsmodus) oder im Inspector befinden.
<SelectControl
label={__('Selected Post', 'awhitepixel')}
options={choices}
value={attributes.selectedPostId}
onChange={(newval) => setAttributes({ selectedPostId: parseInt(newval) })}
/>
Wir setzen das so, dass SelectControl
es sich auf das Attribut bezieht, selectedPostId
das wir im vorherigen Schritt definiert haben. Wir setzen den gespeicherten Wert in der Requisite value
und kümmern uns um die Aktualisierung in der onChange
Requisite – so wie wir es schon einige Male zuvor getan haben. Wir stellen sicher, dass eine Nummer gespeichert wird, indem wir verwenden, parseInt()
da das selectedPostId
vom Typ ist number
. Und wir übergeben das generierte Array von Auswahlmöglichkeiten in der prop options
.
Das ist wirklich alles! Wenn Sie dem Code aus dem vorherigen Schritt gefolgt sind, sollten Sie bereits Code haben, der die gespeicherte Post-ID liest und anzeigt!
Ich empfehle natürlich, die Liste und Auswahl der Posts anders als nur eine einfache Auswahl umzusetzen. Dies ist keine schöne oder benutzerfreundliche Lösung, insbesondere für Websites mit vielen Beiträgen. Apropos Anzahl der Posts, ist Ihnen aufgefallen, dass der Selektor getEntityRecords nur maximal die 10 neuesten Posts zurückgibt? Das ist das Standardverhalten von getEntityRecords, aber wir können die Post-Abfrage ändern, indem wir einen dritten Parameter übergeben.
Ändern Sie die Abfrage für getEntityRecords
Indem wir ein Objekt als dritten Parameter an getEntityRecords übergeben, können wir die Post-Abfrage ändern. getEntityRecords
Wie bereits erwähnt fehlt leider die Dokumentation für. Aber indem ich das ganze Web gelesen habe, habe ich eine Liste möglicher Abfrageargumente zusammengestellt;
per_page
: Auf eine Zahl setzen, um die Anzahl der Posts zu begrenzen. Stellen Sie auf-1
ein, um das Maximum von 100 abzurufen. Standard10
.exclude
: Bestimmte Beiträge von der Abfrage ausschließen. Auf eine Beitrags-ID oder ein Array von Zahlen für mehrere Beitrags-IDs festlegen.parent_exclude
: Bestimmte übergeordnete Beiträge ausschließen. Auf eine Beitrags-ID oder ein Array mehrerer Beitrags-IDs festgelegt.orderby
: Legen Sie die Reihenfolge der Posts fest. Höchstwahrscheinlich können Sie dieselben Parameter wie in orderby von WP_Query verwenden. Kann zB ‘menu_order
‘ sein.order
: Entweder'asc'
oder ‘desc'
für aufsteigende oder absteigende Sortierung.status
: Nach Beitragsstatus filtern. Kann eine Zeichenfolge, eine Zeichenfolge mit mehreren durch Kommas getrennten Status oder ein Array von Statuszeichenfolgen sein. ZB['publish', 'draft']
um sowohl veröffentlichte als auch entworfene Posts abzufragen.categories
: Beiträge nach bestimmten Kategorien filtern. Geben Sie eine Kategorie-ID oder ein Array von Kategorie-IDs an. Ich glaube, das funktioniert nur für Beitragskategorien und nicht für andere benutzerdefinierte Taxonomien.tags
: Beiträge nach bestimmten Tags filtern. Geben Sie eine Tag-ID oder ein Array von Tag-IDs an. Funktioniert nur für Post-Tags und nicht für andere benutzerdefinierte Taxonomien.search
: Fügen Sie eine Suchanfrage (String) hinzu.
Hinweis: Dies ist keine vollständige Liste und kann sich auch ändern!
Ändern wir unsere Abfrage. Wir wollen zwei Dinge tun; Zuerst wollen wir alle Posts holen und nicht nur die 10 neusten. Dazu stellen wir Ihnen -1
zur Verfügung per_page
. Zweitens möchten wir den aktuellen Beitrag aus der Beitragsliste ausschließen, indem wir die aktuelle Beitrags-ID an übergeben exclude
. Es macht oft keinen Sinn, eine Beitragsverknüpfung oder eine Vorschau des aktuellen Beitrags selbst anzuzeigen.
Du denkst vielleicht; Warte, wie bekommen wir die aktuelle Post-ID? Vergessen Sie nicht, dass wir innerhalb der übergeordneten Komponente withSelect
und mit dem select
Selektor auf alle Kerndatenspeicher von WordPress zugreifen können. Die aktuelle Post-ID ist eine natürliche Sache, die in einem der WordPress-Core-Stores gespeichert wird. Darin core/editor
finden wir die Funktion getCurrentPostId()
.
Ändern wir die withSelect
Rückgabe in etwa so:
edit: withSelect(select => {
const currentPostId = select('core/editor').getCurrentPostId();
const query = {
per_page: -1,
exclude: currentPostId
}
return {
posts: select('core').getEntityRecords('postType', 'post', query)
}
})(FirstBlockEdit),
Die obige Änderung ist ziemlich selbsterklärend. Wir generieren ein Abfrageobjekt mit den Eigenschaften per_page
und exclude
und übergeben dies als dritten Parameter an getEntityRecords()
. Jetzt sollte unser props.posts
Inneres der FirstBlockEdit
Komponente alle Posts auflisten, aber den aktuellen Post ausschließen.
Fazit
Dieser Beitrag schließt die Tutorial-Reihe So erstellen Sie benutzerdefinierte Gutenberg-Blöcke ab. Die Serie sollte die Grundlagen der Entwicklung Ihrer eigenen benutzerdefinierten Blöcke durchgehen und Ihnen einen Ausgangspunkt für die Entwicklung Ihrer eigenen und komplexeren Blöcke bieten. Halten Sie auf jeden Fall Ausschau nach weiteren Gutenberg-bezogenen Tutorials hier. Vielleicht finden Sie ein Tutorial, das etwas genauer erklärt, was Sie selbst tun wollten!