Renderizando dados externos de API em blocos WordPress no back-end PlatoBlockchain Data Intelligence. Pesquisa vertical. Ai.

Renderizando dados de API externos em blocos do WordPress no back-end

Esta é uma continuação do meu último artigo sobre “Renderizando dados de API externos em blocos do WordPress no front-end”. Nesse último, aprendemos como pegar uma API externa e integrá-la a um bloco que renderiza os dados buscados no front-end de um site WordPress.

O problema é que conseguimos isso de uma maneira que nos impede de ver os dados no WordPress Block Editor. Em outras palavras, podemos inserir o bloco em uma página, mas não obtemos uma prévia dele. Nós só conseguimos ver o bloco quando ele é publicado.

Vamos revisitar o plug-in de bloco de exemplo que fizemos no último artigo. Só que desta vez, vamos usar o ecossistema JavaScript e React do WordPress para buscar e renderizar esses dados também no Editor de Blocos de back-end.

De onde paramos

Ao iniciarmos isso, aqui está uma demonstração onde chegamos no último artigo que você pode fazer referência. Você deve ter notado que eu usei um render_callback no último artigo para que eu possa usar os atributos no arquivo PHP e renderizar o conteúdo.

Bem, isso pode ser útil em situações em que você pode ter que usar alguma função nativa do WordPress ou PHP para criar blocos dinâmicos. Mas se você quiser usar apenas o ecossistema JavaScript e React (JSX, especificamente) do WordPress para renderizar o HTML estático junto com os atributos armazenados no banco de dados, você só precisa se concentrar no Edit e Save funções do plugin de bloco.

  • A Edit A função renderiza o conteúdo com base no que você deseja ver no Editor de blocos. Você pode ter componentes interativos do React aqui.
  • A Save A função renderiza o conteúdo com base no que você deseja ver no front-end. Você não pode ter os componentes regulares do React ou os ganchos aqui. Ele é usado para retornar o HTML estático que é salvo em seu banco de dados junto com os atributos.

A Save função é onde estamos saindo hoje. Podemos criar componentes interativos no front-end, mas para isso precisamos incluí-los manualmente e acessá-los fora do Save função em um arquivo como fizemos no último artigo.

Então, vou cobrir o mesmo terreno que fizemos no artigo anterior, mas desta vez você pode ver a visualização no Editor de Blocos antes você publicá-lo no front-end.

Os suportes do bloco

Eu intencionalmente deixei de fora quaisquer explicações sobre o edit adereços da função no último artigo porque isso teria tirado o foco do ponto principal, a renderização.

Se você tem experiência em React, provavelmente entenderá do que estou falando, mas se você é novo nisso, recomendo verificando componentes e adereços na documentação do React.

Se registrarmos o props object para o console, ele retorna uma lista de funções e variáveis ​​do WordPress relacionadas ao nosso bloco:

Renderizando dados de API externos em blocos do WordPress no back-end

Precisamos apenas do attributes objeto e o setAttributes função que vou desestruturar do props objeto no meu código. No último artigo, modifiquei o código do RapidAPI para poder armazenar os dados da API por meio de setAttributes(). Os adereços são apenas legíveis, por isso não podemos modificá-los diretamente.

Adereços de bloco são semelhantes a variáveis ​​de estado e setState no React, mas o React funciona no lado do cliente e setAttributes() é usado para armazenar os atributos permanentemente no banco de dados do WordPress após salvar a postagem. Então, o que precisamos fazer é salvá-los para attributes.data e, em seguida, chame isso como o valor inicial para o useState() variável.

A edit função

Vou copiar e colar o código HTML que usamos no football-rankings.php no último artigo e edite-o um pouco para mudar para o plano de fundo do JavaScript. Lembra como criamos dois arquivos adicionais no último artigo para o estilo e os scripts do front-end? Com a maneira como estamos abordando as coisas hoje, não há necessidade de criar esses arquivos. Em vez disso, podemos mover tudo para o Edit função.

Código completo
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}
); })}
); } )}
)}
); }

Eu incluí o gancho React useState() da @wordpress/element em vez de usá-lo da biblioteca React. Isso porque se eu carregasse da maneira normal, ele baixaria o React para cada bloco que estou usando. Mas se estou usando @wordpress/element ele carrega de uma única fonte, ou seja, a camada do WordPress em cima do React.

Desta vez, também não embrulhei o código dentro useEffect() mas dentro de uma função que é chamada apenas ao clicar em um botão para que tenhamos uma visualização ao vivo dos dados buscados. Eu usei uma variável de estado chamada apiData para renderizar a tabela de classificação condicionalmente. Então, uma vez que o botão é clicado e os dados são buscados, estou configurando apiData para os novos dados dentro do fetchData() e há uma rerenderização com o HTML da tabela de classificação de futebol disponível.

Você notará que assim que a postagem for salva e a página for atualizada, a tabela de classificação desaparecerá. Isso porque estamos usando um estado vazio (null) Para apiDatavalor inicial de. Quando a postagem é salva, os atributos são salvos no attributes.data objeto e nós o chamamos como o valor inicial para o useState() variável como esta:

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

A save função

Vamos fazer quase exatamente a mesma coisa com o save função, mas modifique-o um pouco. Por exemplo, não há necessidade do botão "Buscar dados" no front end, e o apiData variável de estado também é desnecessária porque já estamos verificando no edit função. Mas precisamos de um aleatório apiData variável que verifica attributes.data para renderizar condicionalmente o JSX ou então ele lançará erros indefinidos e a interface do usuário do Block Editor ficará em branco.

Código completo
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}
); })}
); })}
)} ); }

Se você estiver modificando o save função após um bloco já estar presente no Editor de Blocos, ele mostraria um erro como este:

O bloco de rankings de futebol no Editor de blocos do WordPress com uma mensagem de erro informando que o bloco contém um erro inesperado.
Renderizando dados de API externos em blocos do WordPress no back-end

Isso ocorre porque a marcação no conteúdo salvo é diferente da marcação em nosso novo save função. Como estamos no modo de desenvolvimento, é mais fácil remover o bock da página atual e reinseri-lo como um novo bloco — dessa forma, o código atualizado é usado e as coisas voltam a sincronizar.

Esta situação de removê-lo e adicioná-lo novamente pode ser evitada se tivéssemos usado o render_callback já que a saída é dinâmica e controlada pelo PHP em vez da função save. Portanto, cada método tem suas próprias vantagens e desvantagens.

Tom Nowell fornece uma explicação completa sobre o que não fazer em um save funcionam em este estouro de pilha responder.

Estilizando o bloco no editor e no front end

Em relação ao estilo, será quase a mesma coisa que vimos no artigo anterior, mas com algumas pequenas alterações que expliquei nos comentários. Estou apenas fornecendo os estilos completos aqui, já que isso é apenas uma prova de conceito, em vez de algo que você deseja copiar e colar (a menos que você realmente precise de um bloco para mostrar os rankings de futebol com esse estilo). E observe que ainda estou usando o SCSS que compila para CSS na compilação.

Estilos de editor
/* 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);
    }
  }
}
Estilos de front-end
/* 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;
    }
  }
}

Nós adicionamos isso a src/style.scss que cuida do estilo no editor e no frontend. Não poderei compartilhar o URL de demonstração, pois exigiria acesso de editor, mas tenho um vídeo gravado para você ver a demonstração:


Bem legal, certo? Agora temos um bloco totalmente funcional que não apenas renderiza no front-end, mas também busca dados da API e renderiza ali mesmo no Editor de Blocos — com um botão de atualização para inicializar!

Mas se quisermos tomar cheio vantagem do WordPress Block Editor, devemos considerar mapear alguns dos elementos da interface do usuário do bloco para controles de bloco para coisas como definir cor, tipografia e espaçamento. Esse é um bom próximo passo na jornada de aprendizado do desenvolvimento de blocos.

Carimbo de hora:

Mais de Truques CSS