Hand Holding React Sticker
, ,

Wszystko co musisz wiedzieć o React w kontekście pisania własnych bloków Gutenberga

Do tej pory developerzy WordPress byli przyzwyczajeni do konkretnego zestawu technologii do tworzenia zarówno motywów jak i wtyczek do WordPressa.

Wiedza o PHP, HTML i odrobina JavaScriptu (a czasem jQuery) w zupełności wystarczała aby wykonać większość zadań związanych z niestandardowym developmentem WP.

Wraz z wprowadzeniem w WordPress 5.9 nowego edytora Gutenberg, otrzymaliśmy mała rewolucję w wyżej wymienionym zestawie. Mowa oczywiście o React w którym sam Gutenberg jest napisany.

Czy muszę znać React?

Teoretycznie, aby rozszerzać edytor Gutenberg nie potrzebujesz uczyć się samego Reacta. Gutenberg został zaprojektowany tak aby był niezależny od użytej biblioteki.

W praktyce jednak, wiedza na temat React jest bardzo przydatna przy tworzeniu nowych bloków lub rozszerzaniu bloków core.

Znajomość React jest niezbędna jeśli zamierzasz kontrybuować kod do Gutenberga.

Jak zacząć naukę React?

W tym wpisie nie będziemy skupiać się na podstawach React lecz ich znajomość będzie ważna aby zrozumieć niektóre koncepty stojące za działaniem Gutenberga.

W internecie jest wiele darmowych materiałów na temat samego Reacta a jednym z najlepszych jest oficjalna dokumentacja. Zachęcam każdego WordPress developera od zaczęcia w tym miejscu. Kiedy już choć odrobinę poznałeś zasadę działania React możesz przejść do dalszej części tego artykułu.

Obserwuj stronę Akademii Gutenberga bo w niedalekiej przyszłości znajdziesz tutaj sporo wpisów poświęconych nauce Reacta dla WordPress developerów.

React w kontekście Gutenberga

Gutenberg to React. Na poniższych przykładach widać wpływ Reacta na development bloków Gutenberga. A to tylko wierzchołek góry lodowej.

1. Blok Gutenberga to seria komponentów React

W drugim parametrze funkcji registerBlockType przekazujemy obiekt i podajemy pola editsave. Pierwsze z nich definiuje wygląd i zachowanie bloku w edytorze, a drugie na „froncie” strony.

Oba te pola akceptują komponent React jako wartość.

import { registerBlockType } from "@wordpress/blocks";

import Edit from "./edit"; // komponent React
import Save from "./save"; // komponent React
import metadata from "./block.json";

registerBlockType(metadata.name, {
  edit: Edit,
  save: Save,
});

W dalszej części tego wpisu znajdziesz demonstrację działania wszystkich konceptów w praktycznym przykładzie.

Chcesz zobaczyć jak możesz zacząć tworzyć bloki bez żadnych narzędzi developerskich? Sprawdź: Jak stworzyć swój pierwszy blok Gutenberga w 15 minut jako developer PHP bez środowiska lokalnego.

2. Elementy UI edytora to komponenty React

Wpływ Reacta na WordPressa widać najlepiej w paczce @wordpress/components.

Już samo słowo components może dać nam do zrozumienia, że mamy do czynienia z Reactem i jego modelem mentalnym.

Weźmy na przykład komponent Button:

Użycie takiego buttona w naszym kodzie:

import { Button } from '@wordpress/components';

// komponent React!
function MyButton() {
  return (
    <Button variant="secondary">Click me!</Button>;
  )
}

Biblioteka komponentów @wordpress/components zawiera obecnie 130 komponentów. Od najprostszych jak Card, Panel, Divider po bardziej złożone jak ColorPicker, ColorPalette, DuotonePicker czy DateTime.

Szczegóły dotyczące każdego z nich znajdziesz w dokumentacji komponentów.

3. Stan, efekty oraz całe API React jest wystawione przez WordPressa do użycia przez developerów

Kiedy znajdujemy się na stronie która wyświetla edytor Gutenberg, mamy dostęp do globalnej zmiennej wp. Po zbadaniu wp.element okazuje się że zawiera ona całe API React w tym najbardziej popularne useEffect, useState, useCallback, createElement etc…

To oznacza że w tworząc własny blok możemy używać wszystkich tych funkcji wg. potrzeby, na przykład:

import { useState } from '@wordpress/element';
import { Button } from '@wordpress/components';

// komponent React!
function MyButton() {
  const [ open, setOpen ] = useState( false );
   
  const onButtonClick = () =&gt; {
    setOpen( true );
  }

  return (
    <div>
      <Button onClick={ onButtonClick }>
        Pokaż więcej
      </Button>
      {open && (
        <span>
          widoczne tylko gdy open === true
        </span>
      )}
    <div>
  )
}

Klasyczny counter w React jako blok Gutenberga

Zaimplementujmy najprostszy przykład z dokumentacji React: Counter (number).

Kod używający czysty React:

import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You pressed me {count} times
    </button>
  );
}

Licznik w edycji bloku

W naszym przypadku chcemy aby ten counter znalazł się w edytorze, podczas edytowania po wstawieniu naszego bloku.

Najpierw block.json

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "akademiagutenberga/counter",
  "version": "0.1.0",
  "title": "Counter",
  "editorScript": "file:./index.js"
}

Następnie potrzebujemy plik index.js wskazany w editorScript

import { registerBlockType } from "@wordpress/blocks";

// 1. Importujemy useState z '@wordpress/element', nie 'react'
import { useState } from "@wordpress/element";

// 2. Importujemy dane bloku z pliku block.json
import metadata from "./block.json";

// 3. Funkcja Edit to identyczny komponent React jak w przykładzie
function Edit() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You pressed me {count} times
    </button>
  );
}

// 4. Komponent save jest w tym przykładzie nieużywany
function save() {
  return <div>To co pokaże się na froncie</div>;
}

// 5. Rejestrujemy blok podając w edit komponent Edit
registerBlockType(metadata.name, {
  edit: Edit,
  save,
});

Jak widać API React i Gutenberga pokrywają się prawie w całości.

Wynikiem dodania takiego bloku w Gutenbergu będzie:

Stworzony w ten sposób counter (lub dowolny komponent), możemy również użyć w pasku toolbar lub w panelu bocznym!

Licznik w pasku kontrolek bloku (BlockControls)

import { registerBlockType } from "@wordpress/blocks";
import { useState } from "@wordpress/element";

// 1. Importujemy BlockControls
import { BlockControls } from "@wordpress/block-editor";

import metadata from "./block.json";

// 2. Wyciągamy counter do osobnego komponentu
function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You pressed me {count} times
    </button>
  );
}

// 3. Używamy counter wewnątrz komponentu <BlockControls />
function Edit() {
  return (
    <div >
      <BlockControls>
        <Counter />
      </BlockControls>
    </div>
  );
}

function save() {
  return <div>To co pokaże się na froncie</div>;
}

registerBlockType(metadata.name, {
  edit: Edit,
  save,
});

Rezultat:

Licznik w pasku bocznym bloku (InspectorControls)

import { registerBlockType } from "@wordpress/blocks";
import { useState } from "@wordpress/element";

// 1. Importujemy InspectorControls
import { InspectorControls } from "@wordpress/block-editor";

import metadata from "./block.json";

// 2. Wyciągamy counter do osobnego komponentu
function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      You pressed me {count} times
    </button>
  );
}

// 3. Używamy counter wewnątrz komponentu <InspectorControls />
function Edit() {
  return (
    <div >
      <InspectorControls>
        <Counter />
      </InspectorControls>
    </div>
  );
}

function save() {
  return <div>To co pokaże się na froncie</div>;
}

registerBlockType(metadata.name, {
  edit: Edit,
  save,
});

Rezultat:

Bonus: lepszy UI w pasku bocznym dzięki komponentom UI WordPressa

Pewnie zauważyłeś że przycisk wyświetlony w pasku bocznym nie miał żadnej przestrzeni wokół siebie a w dodatku użyty został standardowy element <button>, który w żaden sposób nie został ostylowany.

Aby sprawić że zacznie to wyglądać o wiele lepiej użyjemy komponentów ze wspomnianej już paczki @wordpress/components:

  • do lepszego spacingu w sidebarze użyjemy komponentu Card,
  • ładniejszy przycisk uzyskamy używając komponent Button

Koniec teorii, oto kod!

import { registerBlockType } from "@wordpress/blocks";
import { useState } from "@wordpress/element";
import { InspectorControls } from "@wordpress/block-editor";
import { Card, CardBody, Button } from "@wordpress/components";

import metadata from "./block.json";

function Counter() {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <Card>
      <CardBody>
        <Button variant="primary" onClick={handleClick}>
          You pressed me {count} times
        </Button>
      </CardBody>
    </Card>
  );
}

function Edit() {
  return (
    <div>
      <InspectorControls>
        <Counter />
      </InspectorControls>
    </div>
  );
}

function save() {
  return <div>To co pokaże się na froncie</div>;
}

registerBlockType(metadata.name, {
  edit: Edit,
  save,
});

A oto rezultat. Od razu lepiej, prawda?

Podsumowanie i kod źródłowy

Jeśli możemy osadzić w Gutenbergu prosty licznik napisany w React to możemy tam dodać także inne elementy czy nawet całe aplikacje React.

Dostępne obecnie narzędzia takie jak @wordpress/scripts czynią rozszerzanie edytora zadaniem które nie spędza snu z powiek.

Czy już masz pomysły w jaki sposób możesz uczynić Gutenberga jeszcze potężniejszym narzędziem dzięki rozszerzeniu jego możliwości?

Zachęcam cię do eksplorowania tego tematu bo jest to przyszłość developmentu w WordPressie.

Miłego kodowania!

Podoba ci się treść na Akademii Gutenberga? Zapisz się do naszej listy mailingowej aby być na bieżąco z nowymi artykułami!

Podobało się? Podziel się z innymi

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *