
[ad_1]
Até agora, abordamos como trabalhar com dados de uma API externa em um bloco personalizado do WordPress. Percorremos o processo de busca desses dados para uso no front-end de um site WordPress e como renderizá-los diretamente no WordPress Block Editor ao colocar o bloco no conteúdo. Desta vez, vamos unir esses dois artigos acessando o painel de controle do editor de blocos para criar uma interface do usuário de configurações para o bloco que criamos.
Trabalhando com APIs externas em blocos do WordPress
Você conhece o painel de controle a que me refiro, certo? É o painel à direita que contém as configurações de postagem e bloco no editor de bloco.

Está vendo aquela área destacada em vermelho? Esse é o painel de controle. Um bloco de parágrafo está atualmente selecionado e suas configurações são exibidas no painel. Podemos mudar estilos, cores, tipografia… uma série de coisas!
Bem, isso é exatamente o que estamos fazendo desta vez. Vamos criar os controles para as configurações do bloco Football Rankings que trabalhamos nos últimos dois artigos. Da última vez, fizemos um botão em nosso bloco que busca os dados externos do ranking de futebol. Já sabíamos o URL e os endpoints de que precisávamos. Mas e se quisermos buscar a classificação de um país diferente? Ou talvez uma liga diferente? Que tal dados de uma temporada diferente?
Precisamos de controles de formulário para fazer isso. Poderíamos usar componentes React interativos — como React-Select — para navegar pelas várias opções de API disponíveis para analisar esses dados. Mas não há necessidade disso, já que o WordPress vem com vários componentes principais aos quais nos conectamos!
A documentação para esses componentes — chamada InspectorControls
— está melhorando no Manual do Editor de Blocos do WordPress. Isso ficará ainda melhor com o tempo, mas, enquanto isso, também temos os sites WordPress Gutenberg Storybook e WordPress Gutenberg Components para obter ajuda adicional.
A arquitetura da API
Antes de nos envolvermos em qualquer coisa, é uma boa ideia mapear o que precisamos em primeiro lugar. Mapeei a estrutura dos dados RapidAPI que estamos buscando para sabermos o que está disponível para nós:

Temporadas e países são dois endpoints de nível superior que mapeiam para um endpoint de liga. A partir daí, temos o restante dos dados que já estamos usando para preencher a tabela de classificação. Então, o que queremos fazer é criar configurações no Editor de blocos do WordPress que filtrem os dados por Temporada, País e Liga e, em seguida, passar esses dados filtrados para a tabela de classificação. Isso nos dá a capacidade de soltar o bloco em qualquer página ou postagem do WordPress e exibir variações dos dados no bloco.
Para obter a classificação, precisamos primeiro obter as ligas. E para obter as ligas, primeiro precisamos obter os países e/ou as temporadas. Você pode visualizar os vários endpoints no painel RapidAPI.

Existem diferentes combinações de dados que podemos usar para preencher as classificações, e você pode ter uma preferência para quais dados deseja. Para este artigo, vamos criar as seguintes opções no painel de configurações do bloco:
- Escolha o país
- Escolha a Liga
- Escolha a temporada
Em seguida, teremos um botão para enviar essas seleções e buscar os dados relevantes e passá-los para a tabela de classificação.
Carregar e armazenar uma lista de países
Não podemos selecionar para qual país queremos dados se não tivermos uma lista de países para escolher. Portanto, nossa primeira tarefa é obter uma lista de países da RapidAPI.
O ideal é buscar a lista de países quando o bloqueio for efetivamente utilizado na página ou no conteúdo do post. Não há necessidade de buscar nada se o bloco não estiver em uso. A abordagem é muito semelhante ao que fizemos no primeiro artigo, com a diferença de que estamos usando um endpoint de API diferente e atributos diferentes para armazenar a lista de países retornados. Existem outras formas do WordPress para buscar dados, como api-fetch, mas isso está fora do escopo do que estamos fazendo aqui.
Podemos incluir a lista de países manualmente depois de copiá-la dos dados da API ou podemos usar uma API ou biblioteca separada para preencher os países. Mas a API que estamos usando já tem uma lista de países, então eu usaria apenas um de seus endpoints. Vamos garantir que a lista inicial de países seja carregada quando o bloco for inserido na página ou postar conteúdo no editor de blocos:
// edit.js
const [countriesList, setCountriesList] = useState(null);
useEffect(() => {
let countryOptions = {
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/countries", countryOptions)
.then( (response) => response.json() )
.then( (response) => {
let countriesArray = { ...response };
console.log("Countries list", countriesArray.response);
setCountriesList(countriesArray.response);
})
.catch((err) => console.error(err));
}, []);
Temos uma variável de estado para armazenar a lista de países. Em seguida, vamos importar um componente do pacote @wordpress/block-editor chamado InspectorControls
que é onde todos os componentes que precisamos para criar nossos controles de configurações estão localizados.
import { InspectorControls } from "@wordpress/block-editor";
O repositório GitHub do pacote faz um bom trabalho explicando InspectorControls
. Em nosso exemplo, podemos usá-lo para controlar as configurações de dados da API, como País, Liga e Temporada. Aqui está uma prévia para que você tenha uma ideia da IU que estamos fazendo:

E uma vez que essas seleções são feitas nas configurações do bloco, nós as usamos no bloco Edit
função:
<InspectorControls>
{ countriesList && (
<LeagueSettings
props={props}
countriesList={ countriesList }
setApiData={ setApiData }
></LeagueSettings>
)}
</InspectorControls>
Aqui, estou me certificando de que estamos usando renderização condicional para que a função carregue apenas o componente depois a lista de países é carregada. Se você está se perguntando sobre isso LeagueSettings
componente, é um componente personalizado que criei em um separado components
subpasta no bloco para que possamos ter um ambiente mais limpo e organizado Edit
função em vez de centenas de linhas de dados de país para lidar em um único arquivo.

Podemos importá-lo para o edit.js
arquivo assim:
import { LeagueSettings } from "./components/LeagueSettings";
Em seguida, estamos passando os adereços necessários para o LeagueSettings
componente do pai Edit
componente para que possamos acessar as variáveis de estado e atributos do LeagueSettings
componente filho. Também podemos fazer isso com outros métodos, como a API de contexto, para evitar a perfuração de prop, mas o que temos agora é perfeitamente adequado para o que estamos fazendo.
As outras partes do Edit
função também pode ser convertida em componentes. Por exemplo, o código de classificação da liga pode ser colocado dentro de um componente separado — como talvez LeagueTable.js
— e então importados como nós importamos LeagueSettings
no Edit
função.
Dentro de LeagueSettings.js
Arquivo
LeagueSettings
é como outro componente React do qual podemos desestruturar as props do componente pai. Vou usar três variáveis de estado e uma variável adicional leagueID
estado porque vamos extrair o ID do league
objeto:
const [country, setCountry] = useState(null);
const [league, setLeague] = useState(null);
const [season, setSeason] = useState(null);
const [leagueID, setLeagueID] = useState(null);
A primeira coisa que vamos fazer é importar o PanelBody
componente do pacote @wordpress/block-editor:
import { PanelBody } from "@wordpress/block-editor";
…e incluí-lo em nosso return
função:
<PanelBody title="Data settings" initialOpen={false}></PanelBody>
Existem outras tags e atributos de painel – é apenas minha preferência pessoal usar esses. Nenhum dos outros é necessário… mas veja todos os componentes que temos disponíveis para fazer um painel de configurações! Eu gosto da simplicidade do PanelBody
para o nosso caso de uso. Ele se expande e se fecha para revelar as configurações suspensas do bloco e é isso.
Falando nisso, temos uma escolha a fazer para essas seleções. Poderíamos usar o SelectControl
componente ou um ComboBoxControl
que os documentos descrevem como “uma versão aprimorada de um SelectControl
, além de poder pesquisar opções usando uma entrada de pesquisa.” Isso é bom para nós porque a lista de países pode ficar muito longa e os usuários poderão fazer uma consulta de pesquisa ou selecionar em uma lista.
Aqui está um exemplo de como um ComboboxControl
poderia funcionar para nossa lista de países:
<ComboboxControl
label="Choose country"
value={country}
options={ filteredCountryOptions }
onChange={ (value) => handleCountryChange(value) }
onInputChange={ (inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
o ComboboxControl
é configurável no sentido de que podemos aplicar tamanhos diferentes para o rótulo e os valores do controle:
{
value: 'small',
label: 'Small',
},
Mas nossos dados de API não estão nessa sintaxe, então podemos converter o countriesList
array que vem do componente pai quando o bloco é incluído:
let setupCountrySelect;
setupCountrySelect = countriesList.map((country) => {
return {
label: country.name,
value: country.name,
};
});
Quando um país é selecionado na ComboboxControl
o valor do país muda e filtramos os dados de acordo:
function handleCountryChange(value) {
// Set state of the country
setCountry(value);
// League code from RapidAPI
const options = {
method: "GET",
headers: {
"X-RapidAPI-Key": "Your RapidAPI key",
"X-RapidAPI-Host": "api-football-v1.p.rapidapi.com",
},
};
fetch(`https://api-football-v1.p.rapidapi.com/v3/leagues?country=${value}`, options)
.then((response) => response.json())
.then((response) => {
return response.response;
})
.then((leagueOptions) => {
// Set state of the league variable
setLeague(leagueOptions);
// Convert it as we did for Country options
setupLeagueSelect = leagueOptions.map((league) => {
return {
label: league.league.name,
value: league.league.name,
};
});
setFilteredLeagueOptions(setupLeagueSelect);
})
.catch((err) => console.error(err));
}
Observe que estou usando outras três variáveis de estado para lidar com as mudanças quando a seleção do país muda:
const [filteredCountryOptions, setFilteredCountryOptions] = useState(setupCountrySelect);
const [filteredLeagueOptions, setFilteredLeagueOptions] = useState(null);
const [filteredSeasonOptions, setFilteredSeasonOptions] = useState(null);
E as outras opções de configuração?
Vou mostrar o código que usei para as outras configurações, mas tudo o que ele faz é levar em consideração os casos normais ao definir erros para casos especiais. Por exemplo, haverá erros em alguns países e ligas porque:
- não há classificação para algumas ligas, e
- algumas ligas têm classificações, mas não estão em uma única tabela.
Este não é um tutorial de JavaScript ou React, portanto, deixarei você lidar com os casos especiais da API que planeja usar:
function handleLeagueChange(value) {
setLeague(value);
if (league) {
const selectedLeague = league.filter((el) => {
if (el.league.name === value) {
return el;
}
});
if (selectedLeague) {
setLeague(selectedLeague[0].league.name);
setLeagueID(selectedLeague[0].league.id);
setupSeasonSelect = selectedLeague[0].seasons.map((season) => {
return {
label: season.year,
value: season.year,
};
});
setFilteredSeasonOptions(setupSeasonSelect);
}
} else {
return;
}
}
function handleSeasonChange(value) {
setSeason(value);
}
Enviando as seleções de configurações
No último artigo, criamos um botão no editor de blocos que busca dados atualizados da API. Não há mais necessidade disso agora que temos configurações. Bem, nós precisamos disso – mas não onde está atualmente. Em vez de tê-lo diretamente no bloco renderizado no editor de blocos, vamos movê-lo para o nosso PanelBody
para enviar as seleções de configurações.
Então, de volta LeagueSettings.js
:
// When countriesList is loaded, show the country combo box
{ countriesList && (
<ComboboxControl
label="Choose country"
value={country}
options={filteredCountryOptions}
onChange={(value) => handleCountryChange(value)}
onInputChange={(inputValue) => {
setFilteredCountryOptions(
setupCountrySelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
)}
// When filteredLeagueOptions is set through handleCountryChange, show league combobox
{ filteredLeagueOptions && (
<ComboboxControl
label="Choose league"
value={league}
options={filteredLeagueOptions}
onChange={(value) => handleLeagueChange(value)}
onInputChange={(inputValue) => {
setFilteredLeagueOptions(
setupLeagueSelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase())
)
);
}}
/>
)}
// When filteredSeasonOptions is set through handleLeagueChange, show season combobox
{ filteredSeasonOptions && (
<>
<ComboboxControl
label="Choose season"
value={season}
options={filteredSeasonOptions}
onChange={(value) => handleSeasonChange(value)}
onInputChange={
(inputValue) => {
setFilteredSeasonOptions(
setupSeasonSelect.filter((option) =>
option.label
.toLowerCase()
.startsWith(inputValue.toLowerCase()
)
);
}
}
/>
// When season is set through handleSeasonChange, show the "Fetch data" button
{
season && (
<button className="fetch-data" onClick={() => getData()}>Fetch data</button>
)
}
</>
</>
)}
Aqui está o resultado!
Estamos em um lugar muito bom com o nosso bloco. Podemos renderizá-lo no editor de blocos e no front-end do site. Podemos buscar dados de uma API externa com base em uma seleção de configurações que criamos que filtram os dados. É muito funcional!
Mas há outra coisa que temos de resolver. Neste momento, quando salvamos a página ou postagem que contém o bloqueio, as configurações que selecionamos para o bloqueio são redefinidas. Em outras palavras, essas seleções não são salvas em nenhum lugar. Há um pouco mais de trabalho para tornar essas seleções persistentes. É para onde planejamos ir no próximo artigo, portanto, fique atento.
[ad_2]
Source link