Bu, hakkındaki son makalemin devamı niteliğindedir. “Harici API Verilerini Ön Uçtaki WordPress Bloklarında Oluşturma”. Sonuncusunda, harici bir API almayı ve onu bir WordPress sitesinin ön ucunda getirilen verileri işleyen bir blokla entegre etmeyi öğrendik.
Mesele şu ki, bunu WordPress Block Editor'daki verileri görmemizi engelleyecek şekilde başardık. Başka bir deyişle, bloğu bir sayfaya ekleyebiliriz ancak önizlemesini alamayız. Bloğu yalnızca yayınlandığında görebiliriz.
Geçen yazıda yaptığımız örnek blok eklentisini tekrar gözden geçirelim. Yalnızca bu sefer, bu verileri arka uç Blok Düzenleyicide de alıp işlemek için WordPress'in JavaScript ve React ekosistemini kullanacağız.
Nereden ayrıldık
Bunu başlatırken, işte bir demo başvurabileceğiniz son makalede geldiğimiz yer. kullandığımı fark etmiş olabilirsiniz. render_callback
PHP dosyasındaki özniteliklerden yararlanabilmem ve içeriği oluşturabilmem için son makaledeki yöntemi.
Dinamik bloklar oluşturmak için bazı yerel WordPress veya PHP işlevlerini kullanmanız gerekebilecek durumlarda bu yararlı olabilir. Ancak, statik HTML'yi veritabanında depolanan niteliklerle birlikte oluşturmak için WordPress'in yalnızca JavaScript ve React (özellikle JSX) ekosisteminden yararlanmak istiyorsanız, yalnızca Edit
ve Save
blok eklentisinin işlevleri.
- The
Edit
işlevi, içeriği Blok Düzenleyicide görmek istediklerinize göre işler. Burada etkileşimli React bileşenlerine sahip olabilirsiniz. - The
Save
işlevi, içeriği ön uçta görmek istediklerinize göre işler. Normal React bileşenlerine veya kancalara burada sahip olamazsınız. Özniteliklerle birlikte veritabanınıza kaydedilen statik HTML'yi döndürmek için kullanılır.
The Save
işlevi, bugün takıldığımız yerdir. Ön uçta etkileşimli bileşenler oluşturabiliriz, ancak bunun için bunları manuel olarak dahil etmemiz ve dışarıdan erişmemiz gerekir. Save
son makalede yaptığımız gibi bir dosyada işlev görür.
Bu yüzden, son makalede yaptığımız aynı zemini ele alacağım, ancak bu sefer önizlemeyi Blok Düzenleyicide görebilirsiniz. önce ön uçta yayınlarsınız.
blok sahne
hakkında herhangi bir açıklamayı kasıtlı olarak dışarıda bıraktım. edit
Son makaledeki işlevin destekleri, çünkü bu, odağı ana nokta olan işlemeden uzaklaştırırdı.
Bir React geçmişinden geliyorsanız, muhtemelen neden bahsettiğimi anlayacaksınız, ancak bu konuda yeniyseniz tavsiye ederim React belgelerinde bileşenleri ve donanımları kontrol etme.
Eğer günlüğe kaydedersek props
nesnesini konsola gönderir, bloğumuzla ilgili WordPress işlevlerinin ve değişkenlerinin bir listesini döndürür:
sadece ihtiyacımız var attributes
nesne ve setAttributes
yapısını bozacağım işlev props
kodumdaki nesne. Son makalede, API verilerini depolayabilmem için RapidAPI'nin kodunu değiştirmiştim. setAttributes()
. Donanımlar yalnızca okunabilir olduğundan, bunları doğrudan değiştiremiyoruz.
Blok destekleri, durum değişkenlerine benzer ve setState
React'te, ancak React istemci tarafında çalışır ve setAttributes()
gönderiyi kaydettikten sonra nitelikleri WordPress veritabanında kalıcı olarak depolamak için kullanılır. Yani, yapmamız gereken onları kurtarmak attributes.data
ve sonra bunu başlangıç değeri olarak adlandırın. useState()
değişkeni.
edit
işlev
The Kullandığımız HTML kodunu kopyalayıp yapıştıracağım. football-rankings.php
son makalede ve JavaScript arka planına geçmek için biraz düzenleyin. Ön uç stili ve betikleri için son makalede nasıl iki ek dosya oluşturduğumuzu hatırlıyor musunuz? Bugün olaylara yaklaşım tarzımızla, bu dosyaları oluşturmaya gerek yok. Bunun yerine, hepsini şuraya taşıyabiliriz: Edit
fonksiyonu.
Tam 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}
{el.team.name}
{played}
{win}
{draw}
{lose}
{goals.for}
{goals.against}
{el.points}
{el.form.split("").map((result) => {
return (
{result}
);
})}
);
}
)}
)}
);
}
React kancasını dahil ettim useState()
itibaren @wordpress/element
React kütüphanesinden kullanmak yerine. Bunun nedeni, normal şekilde yüklersem, kullandığım her blok için React'i indirmesidir. Ama eğer kullanıyorsam @wordpress/element
tek bir kaynaktan, yani React'in üstündeki WordPress katmanından yüklenir.
Bu sefer, kodu da içine sarmadım. useEffect()
ancak, getirilen verilerin canlı bir önizlemesine sahip olmamız için yalnızca bir düğmeye tıklandığında çağrılan bir işlevin içinde. adlı bir durum değişkeni kullandım. apiData
lig tablosunu koşullu hale getirmek için. Bu nedenle, düğme tıklandığında ve veriler alındığında, ayarları yapıyorum apiData
içindeki yeni verilere fetchData()
ve mevcut futbol sıralaması tablosunun HTML'sini içeren bir yeniden oluşturma var.
Gönderi kaydedildiğinde ve sayfa yenilendiğinde lig tablosunun gittiğini fark edeceksiniz. Bunun nedeni boş bir durum kullanıyor olmamızdır (null
) Için apiData
başlangıç değeri. Gönderi kaydedildiğinde, özellikler şuraya kaydedilir: attributes.data
nesne ve biz onu başlangıç değeri olarak adlandırıyoruz useState()
bunun gibi değişken:
const [apiData, setApiData] = useState(attributes.data);
save
işlev
The ile hemen hemen aynı şeyi yapacağız. save
işlev, ancak biraz değiştirin. Örneğin, ön uçtaki "Verileri getir" düğmesine gerek yoktur ve apiData
durum değişkeni de gereksizdir çünkü zaten kontrol ediyoruz. edit
işlev. Ama bir rastgeleye ihtiyacımız var. apiData
kontrol eden değişken attributes.data
JSX'i koşullu olarak oluşturmak için, aksi takdirde tanımlanmamış hatalar atar ve Blok Düzenleyici Kullanıcı Arayüzü boş kalır.
Tam 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}
{el.team.name}
{played}
{win}
{draw}
{lose}
{goals.for}
{goals.against}
{el.points}
{el.form.split("").map((result) => {
return (
{result}
);
})}
);
})}
)}
);
}
üzerinde değişiklik yapıyorsanız save
Blok Düzenleyicide bir blok zaten mevcut olduktan sonra işlev görürse, şuna benzer bir hata gösterir:
Bunun nedeni, kaydedilen içerikteki işaretlemenin yeni içeriğimizdeki işaretlemeden farklı olmasıdır. save
işlev. Geliştirme modunda olduğumuz için, bloğu mevcut sayfadan çıkarmak ve yeni bir blok olarak yeniden eklemek daha kolaydır - bu şekilde, bunun yerine güncellenmiş kod kullanılır ve işler tekrar senkronize edilir.
Kullanmış olsaydık, bu kaldırma ve tekrar ekleme durumundan kaçınılabilir. render_callback
Çıktı dinamik olduğundan ve kaydetme işlevi yerine PHP tarafından kontrol edildiğinden bu yöntem. Yani her yöntemin kendine göre avantajları ve dezavantajları vardır.
Tom Nowell, bir durumda ne yapılmaması gerektiğine dair kapsamlı bir açıklama sağlar. save
içinde işlemek bu Yığın Taşması cevap.
Düzenleyicide ve ön uçta bloğu şekillendirme
Tasarımla ilgili olarak, son makalede baktığımız şeyin hemen hemen aynısı olacak, ancak yorumlarda açıkladığım bazı küçük değişiklikler olacak. Bu, kopyalayıp yapıştırmak isteyeceğiniz bir şeyden ziyade yalnızca bir kavram kanıtı olduğu için burada yalnızca tüm stilleri sağlıyorum (gerçekten futbol sıralamalarını tam olarak böyle bir stilde göstermek için bir bloğa ihtiyacınız yoksa). Ve hala derleme sırasında CSS'ye derleyen SCSS kullandığımı unutmayın.
Düzenleyici stilleri
/* 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);
}
}
}
Ön uç stilleri
/* 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;
}
}
}
bunu ekliyoruz src/style.scss
bu, hem editördeki hem de ön uçtaki stil ile ilgilenir. Editör erişimi gerektireceğinden demo URL'sini paylaşamayacağım, ancak demoyu görmeniz için kaydedilmiş bir videom var:
Oldukça temiz, değil mi? Artık, yalnızca ön uçta işleme yapmakla kalmayan, aynı zamanda API verilerini alan ve doğrudan orada Blok Düzenleyicide işleyen tam işlevli bir bloğa sahibiz — önyükleme için bir yenileme düğmesiyle!
Ama almak istiyorsak tam WordPress Blok Düzenleyicinin avantajı, bloğun bazı kullanıcı arabirimi öğelerini şu şekilde eşlemeyi düşünmeliyiz: blok kontrolleri renk, tipografi ve boşluk ayarı gibi şeyler için. Bu, blok geliştirme öğrenme yolculuğunda güzel bir sonraki adım.