Рендеринг данных внешнего API в блоках WordPress на внутренней стороне PlatoBlockchain Data Intelligence. Вертикальный поиск. Ай.

Рендеринг данных внешнего API в блоках WordPress на серверной части

Это продолжение моей прошлой статьи о «Визуализация данных внешнего API в блоках WordPress на внешнем интерфейсе». В последнем мы узнали, как взять внешний API и интегрировать его с блоком, который отображает полученные данные во внешнем интерфейсе сайта WordPress.

Дело в том, что мы сделали это таким образом, что не можем видеть данные в редакторе блоков WordPress. Другими словами, мы можем вставить блок на страницу, но не получим его предварительный просмотр. Мы видим блок только тогда, когда он опубликован.

Давайте вернемся к примеру блочного плагина, который мы сделали в прошлой статье. Только на этот раз мы собираемся использовать экосистему JavaScript и React WordPress для извлечения и рендеринга этих данных во внутреннем редакторе блоков.

Где мы остановились

Когда мы начинаем это, вот демо где мы приземлились в последней статье, на которую вы можете сослаться. Вы, наверное, заметили, что я использовал render_callback метод в последней статье, чтобы я мог использовать атрибуты в файле PHP и отображать содержимое.

Что ж, это может быть полезно в ситуациях, когда вам, возможно, придется использовать некоторые встроенные функции WordPress или PHP для создания динамических блоков. Но если вы хотите использовать только экосистему JavaScript и React (в частности, JSX) WordPress для отображения статического HTML вместе с атрибутами, хранящимися в базе данных, вам нужно сосредоточиться только на Edit и Save функции блочного плагина.

  • Ассоциация Edit Функция отображает содержимое на основе того, что вы хотите видеть в редакторе блоков. Здесь вы можете иметь интерактивные компоненты React.
  • Ассоциация Save Функция отображает контент в зависимости от того, что вы хотите видеть в интерфейсе. У вас не может быть здесь обычных компонентов React или хуков. Он используется для возврата статического HTML, который сохраняется в вашей базе данных вместе с атрибутами.

Ассоциация Save функция, где мы болтаемся сегодня. Мы можем создавать интерактивные компоненты во внешнем интерфейсе, но для этого нам нужно вручную включить и получить к ним доступ вне интерфейса. Save в файле, как мы это делали в прошлой статье.

Итак, я собираюсь рассказать о том же, что и в прошлой статье, но на этот раз вы можете увидеть предварительный просмотр в редакторе блоков. до вы публикуете его в интерфейсе.

Блок реквизит

Я намеренно опустил какие-либо пояснения по поводу edit функции в последней статье, потому что это отвлекло бы внимание от основного момента, рендеринга.

Если у вас есть опыт работы с React, вы, вероятно, поймете, о чем я говорю, но если вы новичок в этом, я бы порекомендовал проверка компонентов и реквизита в документации React.

Если мы зарегистрируем props объект в консоль, он возвращает список функций и переменных WordPress, связанных с нашим блоком:

Рендеринг данных внешнего API в блоках WordPress на серверной части

Нам нужно только attributes объект и setAttributes функцию, которую я собираюсь деструктурировать из props объект в моем коде. В прошлой статье я модифицировал код RapidAPI, чтобы хранить данные API через setAttributes(). Реквизит доступен только для чтения, поэтому мы не можем изменять его напрямую.

Блочные реквизиты похожи на переменные состояния и setState в React, но React работает на стороне клиента и setAttributes() используется для постоянного хранения атрибутов в базе данных WordPress после сохранения сообщения. Итак, что нам нужно сделать, это сохранить их в attributes.data а затем вызовите это как начальное значение для useState() Переменная.

Ассоциация edit функция

Я собираюсь скопировать и вставить код HTML, который мы использовали в football-rankings.php в прошлой статье и немного отредактируйте его, чтобы перейти к фону JavaScript. Помните, как в прошлой статье мы создали два дополнительных файла для стилей интерфейса и скриптов? С тем, как мы подходим к делу сегодня, нет необходимости создавать эти файлы. Вместо этого мы можем переместить все это в Edit функции.

Полный код
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}
); })}
); } )}
)}
); }

Я включил хук React useState() от @wordpress/element вместо того, чтобы использовать его из библиотеки React. Это потому, что если бы я загружался обычным способом, он загружал бы React для каждого блока, который я использую. Но если я использую @wordpress/element он загружается из одного источника, то есть слоя WordPress поверх React.

На этот раз я также не заворачивал код внутрь useEffect() но внутри функции, которая вызывается только при нажатии на кнопку, чтобы у нас был предварительный просмотр полученных данных в реальном времени. Я использовал переменную состояния, называемую apiData для условного отображения рейтинговой таблицы. Итак, как только кнопка нажата и данные получены, я устанавливаю apiData к новым данным внутри fetchData() и есть повторный рендеринг с HTML-таблицей футбольного рейтинга.

Вы заметите, что после сохранения сообщения и обновления страницы рейтинговая таблица исчезает. Это потому, что мы используем пустое состояние (null) Для apiDataначальное значение. Когда сообщение сохраняется, атрибуты сохраняются в attributes.data объект, и мы называем его начальным значением для useState() такая переменная:

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

Ассоциация save функция

Мы собираемся сделать почти то же самое с save функцию, но немного изменить ее. Например, нет необходимости в кнопке «Получить данные» во внешнем интерфейсе, а apiData переменная состояния также не нужна, потому что мы уже проверяем ее в edit функция. Но нам нужен случайный apiData переменная, которая проверяет attributes.data для условного рендеринга JSX, иначе он выдаст неопределенные ошибки, а пользовательский интерфейс редактора блоков станет пустым.

Полный код
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}
); })}
); })}
)} ); }

Если вы модифицируете save после того, как блок уже присутствует в редакторе блоков, будет отображаться такая ошибка:

Блок футбольного рейтинга в редакторе блоков WordPress с сообщением об ошибке, что блок содержит непредвиденную ошибку.
Рендеринг данных внешнего API в блоках WordPress на серверной части

Это связано с тем, что разметка в сохраненном контенте отличается от разметки в нашем новом save функция. Поскольку мы находимся в режиме разработки, проще удалить блок с текущей страницы и повторно вставить его как новый блок — таким образом, вместо этого будет использоваться обновленный код, и все снова будет синхронизировано.

Этой ситуации удаления и повторного добавления можно было бы избежать, если бы мы использовали render_callback метод, так как вывод является динамическим и управляется PHP вместо функции сохранения. Таким образом, каждый метод имеет свои преимущества и недостатки.

Том Ноуэлл подробно объясняет, чего не следует делать в save функции в это переполнение стека ответ.

Стилизация блока в редакторе и интерфейсе

Что касается стиля, он будет почти таким же, как мы рассматривали в прошлой статье, но с небольшими изменениями, которые я объяснил в комментариях. Я просто предоставляю полные стили здесь, так как это всего лишь доказательство концепции, а не то, что вы хотите скопировать-вставить (если вам действительно не нужен блок для отображения футбольных рейтингов, оформленный именно так). И обратите внимание, что я все еще использую SCSS, который компилируется в CSS при сборке.

Редактор стилей
/* 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 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;
    }
  }
}

Мы добавляем это к src/style.scss который заботится о стиле как в редакторе, так и во внешнем интерфейсе. Я не смогу поделиться демонстрационным URL-адресом, так как для этого потребуется доступ редактора, но у меня есть записанное видео, чтобы вы могли посмотреть демонстрацию:


Довольно аккуратно, правда? Теперь у нас есть полностью функционирующий блок, который не только рендерится во внешнем интерфейсе, но также извлекает данные API и рендерится прямо в редакторе блоков — с кнопкой обновления для загрузки!

Но если мы хотим взять полный преимущества редактора блоков WordPress, мы должны рассмотреть возможность сопоставления некоторых элементов пользовательского интерфейса блока с блок управления для таких вещей, как настройка цвета, типографики и интервалов. Это хороший следующий шаг в обучении разработке блоков.

Отметка времени:

Больше от CSS хитрости