Rendering av extern API-data i WordPress-block på baksidan av PlatoBlockchain Data Intelligence. Vertikal sökning. Ai.

Rendering av extern API-data i WordPress-block på baksidan

Detta är en fortsättning på min senaste artikel om "Återgivning av extern API-data i WordPress-block i användargränssnittet". I den sista lärde vi oss hur man tar ett externt API och integrerar det med ett block som återger hämtad data på fronten av en WordPress-webbplats.

Saken är den att vi åstadkom detta på ett sätt som hindrar oss från att se data i WordPress Block Editor. Med andra ord kan vi infoga blocket på en sida men vi får ingen förhandsvisning av det. Blocket får vi se först när det publiceras.

Låt oss återgå till exempelblockplugin som vi gjorde i den senaste artikeln. Bara den här gången kommer vi att använda JavaScript och React-ekosystemet i WordPress för att hämta och rendera dessa data även i back-end Block Editor.

Där vi slutade

När vi startar detta, här är en demo där vi landade i den sista artikeln som du kan referera till. Du kanske har märkt att jag använde en render_callback metod i den sista artikeln så att jag kan använda attributen i PHP-filen och rendera innehållet.

Tja, det kan vara användbart i situationer där du kanske måste använda någon inbyggd WordPress- eller PHP-funktion för att skapa dynamiska block. Men om du bara vill använda JavaScript och React (JSX, specifikt) ekosystemet i WordPress för att återge den statiska HTML-koden tillsammans med attributen som lagras i databasen, behöver du bara fokusera på Edit och Save funktioner för blockplugin.

  • Smakämnen Edit funktionen återger innehållet baserat på vad du vill se i Block Editor. Du kan ha interaktiva React-komponenter här.
  • Smakämnen Save funktionen återger innehållet baserat på vad du vill se på användargränssnittet. Du kan inte ha de vanliga React-komponenterna eller krokarna här. Den används för att returnera den statiska HTML som sparats i din databas tillsammans med attributen.

Smakämnen Save funktion är där vi umgås idag. Vi kan skapa interaktiva komponenter på front-end, men för det måste vi manuellt inkludera och komma åt dem utanför Save funktion i en fil som vi gjorde i förra artikeln.

Så jag kommer att täcka samma grund som vi gjorde i förra artikeln, men den här gången kan du se förhandsvisningen i Block Editor innan du publicerar den i frontend.

Blockets rekvisita

Jag utelämnade medvetet alla förklaringar om edit funktions rekvisita i den senaste artikeln eftersom det skulle ha tagit fokus från huvudpoängen, renderingen.

Om du kommer från en React-bakgrund kommer du förmodligen att förstå vad jag pratar om, men om du är ny på detta skulle jag rekommendera kolla in komponenter och rekvisita i React-dokumentationen.

Om vi ​​loggar props objekt till konsolen, returnerar den en lista med WordPress-funktioner och variabler relaterade till vårt block:

Rendering av extern API-data i WordPress-block på baksidan

Vi behöver bara attributes objekt och setAttributes funktion som jag kommer att destrukturera från props objekt i min kod. I den förra artikeln hade jag modifierat RapidAPI:s kod så att jag kan lagra API-data igenom setAttributes(). Rekvisita är bara läsbara, så vi kan inte ändra dem direkt.

Blockrekvisita liknar tillståndsvariabler och setState i React, men React arbetar på klientsidan och setAttributes() används för att lagra attributen permanent i WordPress-databasen efter att inlägget har sparats. Så vad vi behöver göra är att spara dem till attributes.data och kalla det sedan som startvärdet för useState() variabel.

Smakämnen edit fungera

Jag kommer att kopiera och klistra in HTML-koden som vi använde i football-rankings.php i den sista artikeln och redigera den lite för att flytta till JavaScript-bakgrunden. Kommer du ihåg hur vi skapade ytterligare två filer i den senaste artikeln för frontend-styling och skript? Med det sätt vi närmar oss saker idag, finns det inget behov av att skapa dessa filer. Istället kan vi flytta allt till Edit funktion.

Fullständig kod
import { useState } from "@wordpress/element";
export default function Edit(props) {
  const { attributes, setAttributes } = props;
  const [apiData, setApiData] = useState(null);
    function fetchData() {
      const options = {
        method: "GET",
        headers: {
          "X-RapidAPI-Key": "Your Rapid API key",
          "X-RapidAPI-Host": "api-football-v1.p.rapidapi.com",
        },
      };
      fetch(
        "https://api-football-v1.p.rapidapi.com/v3/standings?season=2021&league=39",
          options
      )
      .then((response) => response.json())
      .then((response) => {
        let newData = { ...response }; // Deep clone the response data
        setAttributes({ data: newData }); // Store the data in WordPress attributes
        setApiData(newData); // Modify the state with the new data
      })
      .catch((err) => console.error(err));
    }
    return (
      
{apiData && (
Rank
Logo
Team name
GP
GW
GD
GL
GF
GA
Pts
Form history
{/* Usage of [0] might be weird but that is how the API structure is. */} {apiData.response[0].league.standings[0].map((el) => { {/* Destructure the required data from all */} const { played, win, draw, lose, goals } = el.all; return (
{el.rank}
Rendering External API Data in WordPress Blocks on the Back End PlatoBlockchain Data Intelligence. Vertical Search. Ai.
{el.team.name}
{played}
{win}
{draw}
{lose}
{goals.for}
{goals.against}
{el.points}
{el.form.split("").map((result) => { return (
{result}
); })}
); } )}
)}
); }

Jag har inkluderat React-kroken useState() från @wordpress/element istället för att använda det från React-biblioteket. Det beror på att om jag skulle ladda på det vanliga sättet, skulle det ladda ner React för varje block som jag använder. Men om jag använder @wordpress/element det laddas från en enda källa, dvs WordPress-lagret ovanpå React.

Den här gången har jag inte heller packat in koden useEffect() men inuti en funktion som bara anropas när man klickar på en knapp så att vi har en liveförhandsvisning av hämtad data. Jag har använt en tillståndsvariabel som heter apiData att göra serietabellen villkorligt. Så när knappen väl har klickats och data hämtas, ställer jag in apiData till de nya uppgifterna inuti fetchData() och det finns en återgivning med HTML-koden för fotbollsrankningstabellen tillgänglig.

Du kommer att märka att när inlägget har sparats och sidan har uppdaterats är ligatabellen borta. Det beror på att vi använder ett tomt tillstånd (null) för apiDatas initiala värde. När inlägget sparas sparas attributen till attributes.data objekt och vi kallar det som det initiala värdet för useState() variabel så här:

const [apiData, setApiData] = useState(attributes.data);

Smakämnen save fungera

Vi kommer att göra nästan exakt samma sak med save funktion, men modifiera den lite. Till exempel, det finns inget behov av "Hämta data"-knappen på fronten, och apiData tillståndsvariabel är också onödig eftersom vi redan kontrollerar den i edit fungera. Men vi behöver en slump apiData variabel som kollar efter attributes.data för att villkorligt rendera JSX, annars kommer det att skapa odefinierade fel och Block Editor-gränssnittet blir tomt.

Fullständig kod
export default function save(props) {
  const { attributes, setAttributes } = props;
  let apiData = attributes.data;
  return (
    
      {/* Only render if apiData is available */}
      {apiData && (
        
Rank
Logo
Team name
GP
GW
GD
GL
GF
GA
Pts
Form history
{/* Usage of [0] might be weird but that is how the API structure is. */} {apiData.response[0].league.standings[0].map((el) => { const { played, win, draw, lose, goals } = el.all; return (
{el.rank}
Rendering External API Data in WordPress Blocks on the Back End PlatoBlockchain Data Intelligence. Vertical Search. Ai.
{el.team.name}
{played}
{win}
{draw}
{lose}
{goals.for}
{goals.against}
{el.points}
{el.form.split("").map((result) => { return (
{result}
); })}
); })}
)} ); }

Om du ändrar save funktion efter att ett block redan finns i Block Editor, skulle det visa ett fel som detta:

Fotbollsrankingen blockerar i WordPress block Editor med ett felmeddelande om att blocket innehåller ett oväntat fel.
Rendering av extern API-data i WordPress-block på baksidan

Det beror på att uppmärkningen i det sparade innehållet skiljer sig från uppmärkningen i vår nya save fungera. Eftersom vi är i utvecklingsläge är det lättare att ta bort bocken från den aktuella sidan och infoga den igen som ett nytt block — på så sätt används den uppdaterade koden istället och saker och ting är tillbaka i synk.

Denna situation med att ta bort den och lägga till den igen kan undvikas om vi hade använt den render_callback metod eftersom utdata är dynamiskt och styrs av PHP istället för spara-funktionen. Så varje metod har sina egna fördelar och nackdelar.

Tom Nowell ger en grundlig förklaring om vad man inte ska göra i en save funktion i detta Stack Overflow svara.

Styling av blocket i editorn och frontend

Angående stylingen kommer det att vara nästan samma sak som vi tittade på i förra artikeln, men med några mindre ändringar som jag har förklarat i kommentarerna. Jag tillhandahåller bara de fullständiga stilarna här eftersom detta bara är ett bevis på konceptet snarare än något du vill kopiera och klistra in (såvida du inte verkligen behöver ett block för att visa fotbollsrankningar utformade precis så här). Och notera att jag fortfarande använder SCSS som kompilerar till CSS på build.

Redaktörsstilar
/* Target all the blocks with the data-title="Football Rankings" */
.block-editor-block-list__layout 
.block-editor-block-list__block.wp-block[data-title="Football Rankings"] {
  /* By default, the blocks are constrained within 650px max-width plus other design specific code */
  max-width: unset;
  background: linear-gradient(to right, #8f94fb, #4e54c8);
  display: grid;
  place-items: center;
  padding: 60px 0;

  /* Button CSS - From: https://getcssscan.com/css-buttons-examples - Some properties really not needed :) */
  button.fetch-data {
    align-items: center;
    background-color: #ffffff;
    border: 1px solid rgb(0 0 0 / 0.1);
    border-radius: 0.25rem;
    box-shadow: rgb(0 0 0 / 0.02) 0 1px 3px 0;
    box-sizing: border-box;
    color: rgb(0 0 0 / 0.85);
    cursor: pointer;
    display: inline-flex;
    font-family: system-ui, -apple-system, system-ui, "Helvetica Neue", Helvetica, Arial, sans-serif;
    font-size: 16px;
    font-weight: 600;
    justify-content: center;
    line-height: 1.25;
    margin: 0;
    min-height: 3rem;
    padding: calc(0.875rem - 1px) calc(1.5rem - 1px);
    position: relative;
    text-decoration: none;
    transition: all 250ms;
    user-select: none;
    -webkit-user-select: none;
    touch-action: manipulation;
    vertical-align: baseline;
    width: auto;
    &:hover,
    &:focus {
      border-color: rgb(0, 0, 0, 0.15);
      box-shadow: rgb(0 0 0 / 0.1) 0 4px 12px;
      color: rgb(0, 0, 0, 0.65);
    }
    &:hover {
      transform: translateY(-1px);
    }
    &:active {
      background-color: #f0f0f1;
      border-color: rgb(0 0 0 / 0.15);
      box-shadow: rgb(0 0 0 / 0.06) 0 2px 4px;
      color: rgb(0 0 0 / 0.65);
      transform: translateY(0);
    }
  }
}
Front-end stilar
/* Front-end block styles */
.wp-block-post-content .wp-block-football-rankings-league-table {
  background: linear-gradient(to right, #8f94fb, #4e54c8);
  max-width: unset;
  display: grid;
  place-items: center;
}

#league-standings {
  width: 900px;
  margin: 60px 0;
  max-width: unset;
  font-size: 16px;
  .header {
    display: grid;
    gap: 1em;
    padding: 10px;
    grid-template-columns: 1fr 1fr 3fr 4fr 3fr;
    align-items: center;
    color: white;
    font-size: 16px;
    font-weight: 600;
    background-color: transparent;
    background-repeat: no-repeat;
    background-size: contain;
    background-position: right;

    .stats {
      display: flex;
      gap: 15px;
      & > div {
        width: 30px;
      }
    }
  }
}
.league-table {
  background: white;
  box-shadow:
    rgba(50, 50, 93, 0.25) 0px 2px 5px -1px,
    rgba(0, 0, 0, 0.3) 0px 1px 3px -1px;
  padding: 1em;
  .position {
    width: 20px;
  }
  .team {
    display: grid;
    gap: 1em;
    padding: 10px 0;
    grid-template-columns: 1fr 1fr 3fr 4fr 3fr;
    align-items: center;
  }
  .team:not(:last-child) {
    border-bottom: 1px solid lightgray;
  }
  .team-logo img {
    width: 30px;
    top: 3px;
    position: relative;
  }
  .stats {
    display: flex;
    gap: 15px;
    & > div {
      width: 30px;
      text-align: center;
    }
  }
  .last-5-games {
    display: flex;
    gap: 5px;
    & > div {
      width: 25px;
      height: 25px;
      text-align: center;
      border-radius: 3px;
      font-size: 15px;
    & .result-W {
      background: #347d39;
      color: white;
    }
    & .result-D {
      background: gray;
      color: white;
    }
    & .result-L {
      background: lightcoral;
      color: white;
    }
  }
}

Vi lägger till detta src/style.scss som tar hand om stylingen i både editorn och frontend. Jag kommer inte att kunna dela demo-URL eftersom det skulle kräva redaktörsåtkomst men jag har en video inspelad så att du kan se demon:


Ganska snyggt, eller hur? Nu har vi ett fullt fungerande block som inte bara renderar i gränssnittet, utan också hämtar API-data och renderar direkt i blockredigeraren – med en uppdateringsknapp för att starta upp!

Men om vi vill ta full fördelen med WordPress Block Editor, bör vi överväga att kartlägga några av blockets UI-element till blockera kontroller för saker som att ställa in färg, typografi och avstånd. Det är ett trevligt nästa steg i inlärningsresan för blockutveckling.

Tidsstämpel:

Mer från CSS-tricks