এটি সম্পর্কে আমার শেষ নিবন্ধের ধারাবাহিকতা "ফ্রন্ট এন্ডে ওয়ার্ডপ্রেস ব্লকে এক্সটার্নাল এপিআই ডেটা রেন্ডারিং". সেই শেষটিতে, আমরা শিখেছি কিভাবে একটি বাহ্যিক API নিতে হয় এবং এটিকে একটি ব্লকের সাথে একীভূত করতে হয় যা একটি ওয়ার্ডপ্রেস সাইটের সামনের প্রান্তে আনা ডেটা রেন্ডার করে।
জিনিসটি হল, আমরা এটি এমনভাবে সম্পন্ন করেছি যা ওয়ার্ডপ্রেস ব্লক এডিটরে ডেটা দেখতে আমাদের বাধা দেয়। অন্য কথায়, আমরা একটি পৃষ্ঠায় ব্লক সন্নিবেশ করতে পারি কিন্তু আমরা এর কোনো পূর্বরূপ পাই না। এটি প্রকাশিত হলেই আমরা ব্লকটি দেখতে পাই।
চলুন আমরা গত নিবন্ধে তৈরি উদাহরণ ব্লক প্লাগইন পুনরায় দেখুন. শুধুমাত্র এই সময়, আমরা ব্যাক-এন্ড ব্লক এডিটরে সেই ডেটা আনতে এবং রেন্ডার করতে ওয়ার্ডপ্রেসের জাভাস্ক্রিপ্ট এবং প্রতিক্রিয়া ইকোসিস্টেম ব্যবহার করতে যাচ্ছি।
যেখানে আমরা ছেড়ে দিয়েছি
আমরা এটি বন্ধ করার সাথে সাথে, এখানে একটি ডেমো যেখানে আমরা শেষ নিবন্ধে অবতরণ করেছি যা আপনি উল্লেখ করতে পারেন। আপনি হয়তো লক্ষ্য করেছেন যে আমি একটি ব্যবহার করেছি render_callback
গত নিবন্ধে পদ্ধতি যাতে আমি পিএইচপি ফাইলের বৈশিষ্ট্যগুলি ব্যবহার করতে পারি এবং বিষয়বস্তু রেন্ডার করতে পারি।
ঠিক আছে, এটি এমন পরিস্থিতিতে কার্যকর হতে পারে যেখানে আপনাকে গতিশীল ব্লক তৈরি করতে কিছু নেটিভ ওয়ার্ডপ্রেস বা পিএইচপি ফাংশন ব্যবহার করতে হতে পারে। কিন্তু আপনি যদি ডাটাবেসে সংরক্ষিত বৈশিষ্ট্য সহ স্ট্যাটিক এইচটিএমএল রেন্ডার করতে ওয়ার্ডপ্রেসের জাভাস্ক্রিপ্ট এবং প্রতিক্রিয়া (জেএসএক্স, বিশেষভাবে) ইকোসিস্টেম ব্যবহার করতে চান তবে আপনাকে শুধুমাত্র ফোকাস করতে হবে Edit
এবং Save
ব্লক প্লাগইন এর ফাংশন।
- সার্জারির
Edit
আপনি ব্লক এডিটরে যা দেখতে চান তার উপর ভিত্তি করে ফাংশন বিষয়বস্তু রেন্ডার করে। আপনার এখানে ইন্টারেক্টিভ প্রতিক্রিয়া উপাদান থাকতে পারে। - সার্জারির
Save
আপনি সামনের প্রান্তে যা দেখতে চান তার উপর ভিত্তি করে ফাংশন সামগ্রী রেন্ডার করে। আপনার এখানে নিয়মিত প্রতিক্রিয়া উপাদান বা হুক থাকতে পারে না। এটি স্ট্যাটিক এইচটিএমএল ফেরত দিতে ব্যবহৃত হয় যা আপনার ডাটাবেসে বৈশিষ্ট্য সহ সংরক্ষিত হয়।
সার্জারির Save
ফাংশন যেখানে আমরা আজ হ্যাং আউট করছি. আমরা ফ্রন্ট-এন্ডে ইন্টারেক্টিভ কম্পোনেন্ট তৈরি করতে পারি, কিন্তু এর জন্য আমাদেরকে ম্যানুয়ালি অন্তর্ভুক্ত করতে হবে এবং সেগুলোর বাইরে অ্যাক্সেস করতে হবে। Save
একটি ফাইলে ফাংশন যেমন আমরা শেষ নিবন্ধে করেছি।
সুতরাং, আমি গত নিবন্ধে আমরা একই গ্রাউন্ড কভার করতে যাচ্ছি, কিন্তু এবার আপনি ব্লক এডিটরে প্রিভিউ দেখতে পারেন আগে আপনি এটি সামনের প্রান্তে প্রকাশ করুন।
ব্লক প্রপস
আমি ইচ্ছাকৃতভাবে সম্পর্কে কোনো ব্যাখ্যা ছেড়ে দিয়েছি edit
শেষ নিবন্ধে ফাংশন এর প্রপস কারণ এটি মূল পয়েন্ট, রেন্ডারিং থেকে ফোকাস বন্ধ করে দিয়েছে।
আপনি যদি প্রতিক্রিয়া ব্যাকগ্রাউন্ড থেকে আসছেন, আপনি সম্ভবত বুঝতে পারবেন যে আমি কিসের কথা বলছি, কিন্তু আপনি যদি এটিতে নতুন হন তবে আমি সুপারিশ করব প্রতিক্রিয়া ডকুমেন্টেশনে উপাদান এবং প্রপস পরীক্ষা করা.
আমরা লগ যদি props
কনসোলে অবজেক্ট করলে, এটি আমাদের ব্লকের সাথে সম্পর্কিত ওয়ার্ডপ্রেস ফাংশন এবং ভেরিয়েবলের একটি তালিকা প্রদান করে:
আমরা শুধুমাত্র প্রয়োজন attributes
বস্তু এবং setAttributes
ফাংশন যা আমি থেকে ধ্বংস করতে যাচ্ছি props
আমার কোডে অবজেক্ট। গত নিবন্ধে, আমি RapidAPI এর কোড পরিবর্তন করেছি যাতে আমি এর মাধ্যমে API ডেটা সংরক্ষণ করতে পারি setAttributes()
. প্রপগুলি শুধুমাত্র পঠনযোগ্য, তাই আমরা সেগুলি সরাসরি সংশোধন করতে অক্ষম।
ব্লক প্রপস রাষ্ট্র ভেরিয়েবল অনুরূপ এবং setState
প্রতিক্রিয়াতে, তবে প্রতিক্রিয়া ক্লায়েন্টের পক্ষে কাজ করে এবং setAttributes()
পোস্টটি সংরক্ষণ করার পর ওয়ার্ডপ্রেস ডাটাবেসে বৈশিষ্ট্যগুলি স্থায়ীভাবে সংরক্ষণ করতে ব্যবহৃত হয়। সুতরাং, আমাদের যা করতে হবে তা হ'ল তাদের সংরক্ষণ করুন attributes.data
এবং তারপর প্রাথমিক মান হিসাবে যে কল useState()
পরিবর্তনশীল।
edit
ক্রিয়া
সার্জারির আমরা যে এইচটিএমএল কোডটি ব্যবহার করেছি তা আমি কপি-পেস্ট করতে যাচ্ছি football-rankings.php
শেষ নিবন্ধে এবং জাভাস্ক্রিপ্ট ব্যাকগ্রাউন্ডে স্থানান্তর করতে এটিকে সামান্য সম্পাদনা করুন। মনে আছে কিভাবে আমরা ফ্রন্ট এন্ড স্টাইলিং এবং স্ক্রিপ্টের জন্য শেষ নিবন্ধে দুটি অতিরিক্ত ফাইল তৈরি করেছি? যেভাবে আমরা আজকে জিনিসগুলির কাছে যাচ্ছি, সেই ফাইলগুলি তৈরি করার দরকার নেই৷ পরিবর্তে, আমরা এটি সব সরাতে পারেন 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}
{el.team.name}
{played}
{win}
{draw}
{lose}
{goals.for}
{goals.against}
{el.points}
{el.form.split("").map((result) => {
return (
{result}
);
})}
);
}
)}
)}
);
}
আমি প্রতিক্রিয়া হুক অন্তর্ভুক্ত করেছি useState()
থেকে @wordpress/element
প্রতিক্রিয়া লাইব্রেরি থেকে এটি ব্যবহার করার পরিবর্তে। এর কারণ হল আমি যদি নিয়মিত ভাবে লোড করি, তাহলে আমি যে সকল ব্লক ব্যবহার করছি তার জন্য এটি React ডাউনলোড করবে। কিন্তু আমি যদি ব্যবহার করি @wordpress/element
এটি একটি একক উত্স থেকে লোড হয়, অর্থাৎ, প্রতিক্রিয়ার উপরে ওয়ার্ডপ্রেস স্তর।
এই সময়, আমি ভিতরে কোড আবৃত না useEffect()
কিন্তু একটি ফাংশনের ভিতরে যা শুধুমাত্র একটি বোতামে ক্লিক করার সময় কল করা হয় যাতে আমাদের কাছে আনা ডেটার একটি লাইভ প্রিভিউ থাকে। আমি নামক একটি রাষ্ট্র পরিবর্তনশীল ব্যবহার করেছি apiData
শর্তসাপেক্ষে লিগ টেবিল রেন্ডার করতে। সুতরাং, একবার বোতামটি ক্লিক করা হলে এবং ডেটা আনা হয়, আমি সেট করছি apiData
ভিতরে নতুন তথ্য fetchData()
এবং ফুটবল র্যাঙ্কিং টেবিলের এইচটিএমএল সহ একটি রিরেন্ডার আছে।
আপনি লক্ষ্য করবেন যে পোস্টটি সংরক্ষণ করা হলে এবং পৃষ্ঠাটি রিফ্রেশ হয়ে গেলে, লিগ টেবিলটি চলে গেছে। কারণ আমরা একটি খালি অবস্থা ব্যবহার করছি (null
) জন্য apiData
এর প্রাথমিক মান। যখন পোস্টটি সংরক্ষণ করে, তখন বৈশিষ্ট্যগুলি সংরক্ষণ করা হয় attributes.data
বস্তু এবং আমরা এটির জন্য প্রাথমিক মান হিসাবে কল করি useState()
এই মত পরিবর্তনশীল:
const [apiData, setApiData] = useState(attributes.data);
save
ক্রিয়া
সার্জারির আমরা সঙ্গে প্রায় একই সঠিক জিনিস করতে যাচ্ছে save
ফাংশন, কিন্তু এটি একটু সংশোধন করুন। উদাহরণস্বরূপ, সামনের প্রান্তে "ডেটা আনুন" বোতামের কোন প্রয়োজন নেই, এবং apiData
স্টেট ভেরিয়েবলটিও অপ্রয়োজনীয় কারণ আমরা ইতিমধ্যেই এটি পরীক্ষা করছি edit
ফাংশন কিন্তু আমরা একটি র্যান্ডম প্রয়োজন কি apiData
পরিবর্তনশীল যে জন্য চেক attributes.data
শর্তসাপেক্ষে JSX রেন্ডার করতে, অন্যথায় এটি অনির্ধারিত ত্রুটি ফেলবে এবং ব্লক এডিটর UI ফাঁকা হয়ে যাবে।
সম্পূর্ণ কোড
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}
);
})}
);
})}
)}
);
}
আপনি যদি পরিবর্তন করছেন save
ব্লক এডিটরে ইতিমধ্যেই উপস্থিত থাকার পরে ফাংশন, এটি এইরকম একটি ত্রুটি দেখাবে:
কারণ সংরক্ষিত কন্টেন্টের মার্কআপ আমাদের নতুন মার্কআপ থেকে আলাদা save
ফাংশন যেহেতু আমরা ডেভেলপমেন্ট মোডে আছি, বর্তমান পৃষ্ঠা থেকে বকটি সরানো এবং এটিকে একটি নতুন ব্লক হিসাবে পুনরায় সন্নিবেশ করা সহজ - এইভাবে, আপডেট করা কোডটি পরিবর্তে ব্যবহার করা হয় এবং জিনিসগুলি আবার সিঙ্কে ফিরে আসে৷
এটি অপসারণ এবং এটি আবার যোগ করার এই পরিস্থিতি এড়ানো যেতে পারে যদি আমরা ব্যবহার করতাম render_callback
পদ্ধতি যেহেতু আউটপুট গতিশীল এবং সেভ ফাংশনের পরিবর্তে পিএইচপি দ্বারা নিয়ন্ত্রিত। সুতরাং প্রতিটি পদ্ধতির নিজস্ব সুবিধা এবং অসুবিধা রয়েছে।
টম নওয়েল একটি তে কী করা উচিত নয় তার একটি পুঙ্খানুপুঙ্খ ব্যাখ্যা প্রদান করেছেন save
মধ্যে ফাংশন এই স্ট্যাক ওভারফ্লো উত্তর.
সম্পাদক এবং সামনের প্রান্তে ব্লক স্টাইল করা
স্টাইলিং সম্পর্কে, এটি প্রায় একই জিনিস হতে চলেছে যা আমরা গত নিবন্ধে দেখেছি, তবে কিছু ছোটখাটো পরিবর্তনের সাথে যা আমি মন্তব্যে ব্যাখ্যা করেছি। আমি এখানে কেবলমাত্র সম্পূর্ণ শৈলী প্রদান করছি কারণ এটি কেবলমাত্র ধারণার একটি প্রমাণ যা আপনি কপি-পেস্ট করতে চান (যদি না আপনি সত্যিই এভাবে স্টাইল করা ফুটবল র্যাঙ্কিং দেখানোর জন্য একটি ব্লকের প্রয়োজন না হয়)। এবং নোট করুন যে আমি এখনও SCSS ব্যবহার করছি যা বিল্ডে সিএসএসে কম্পাইল করে।
সম্পাদক শৈলী
/* 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 ডেটা নিয়ে আসে এবং ব্লক এডিটরে রেন্ডার করে — বুট করার জন্য একটি রিফ্রেশ বোতাম সহ!
কিন্তু আমরা যদি নিতে চাই সম্পূর্ণ ওয়ার্ডপ্রেস ব্লক এডিটরের সুবিধা, আমাদের ব্লকের কিছু UI উপাদানের ম্যাপিং বিবেচনা করা উচিত ব্লক নিয়ন্ত্রণ রঙ, টাইপোগ্রাফি এবং ব্যবধান নির্ধারণের মতো জিনিসগুলির জন্য। ব্লক ডেভেলপমেন্ট শেখার যাত্রায় এটি একটি চমৎকার পরবর্তী ধাপ।