Background Image Upload (MediaUpload, apiFetch, useEffect)
Fitur yang Dibangun
Menambahkan kemampuan untuk mengupload background image pada banner block melalui sidebar editor.
Import yang Diperlukan
import {
InspectorControls,
MediaUpload,
MediaUploadCheck
} from "@wordpress/block-editor";
import {
Button,
PanelBody,
PanelRow
} from "@wordpress/components";
import apiFetch from "@wordpress/api-fetch";
import { useEffect } from "@wordpress/element";Catatan: Import
useEffectdari@wordpress/element(bukan langsung dari React). WordPress membungkus React sebagai abstraction layer.
Attributes untuk Image
attributes: {
imageID: { type: "number" },
imgURL: { type: "string" }
}| Attribute | Fungsi |
|---|---|
imageID | ID media dari WordPress media library |
imgURL | URL gambar (disimpan setelah API fetch) |
MediaUpload di InspectorControls
function EditComponent(props) {
return (
<>
<InspectorControls>
<PanelBody title="Background Image" initialOpen={true}>
<PanelRow>
<MediaUploadCheck>
<MediaUpload
onSelect={(media) => props.setAttributes({ imageID: media.id })}
value={props.attributes.imageID}
render={({ open }) => (
<Button onClick={open}>Choose Image</Button>
)}
/>
</MediaUploadCheck>
</PanelRow>
</PanelBody>
</InspectorControls>
{/* ... konten block lainnya */}
</>
);
}Props MediaUpload
| Prop | Fungsi |
|---|---|
onSelect | Callback saat gambar dipilih → simpan media.id |
value | ID media yang sedang aktif |
render | Function yang return UI button → destructure { open } |
Mengapa MediaUploadCheck?
Wrapper MediaUploadCheck memastikan button hanya muncul jika user memiliki izin untuk upload media.
Fetch URL Gambar dengan apiFetch & useEffect
Masalah
WordPress media picker memberikan ID media, tapi kita butuh URL gambar dengan ukuran custom (misal: page_banner).
Ukuran gambar custom (seperti page_banner) tidak tersedia di data default yang dikembalikan media picker.
Solusi: REST API + useEffect
function EditComponent(props) {
// Watch perubahan imageID
useEffect(() => {
if (props.attributes.imageID) {
async function fetchImage() {
const response = await apiFetch({
path: `/wp/v2/media/${props.attributes.imageID}`,
method: "GET"
});
props.setAttributes({
imgURL: response.media_details.sizes.page_banner.source_url
});
}
fetchImage();
}
}, [props.attributes.imageID]);
// ...
}Alur Kerja
1. User pilih gambar → onSelect → imageID disimpan
2. useEffect mendeteksi imageID berubah
3. apiFetch ke /wp/v2/media/{id}
4. Response berisi media_details.sizes.page_banner.source_url
5. imgURL disimpan ke attributes
6. Background image ditampilkanEndpoint REST API
GET /wp/v2/media/{id}Response path ke URL gambar:
response.media_details.sizes.page_banner.source_urlJika ukuran custom tidak ada, gunakan ukuran default:
response.source_url
Fallback Image dengan wp_localize_script
Masalah
Bagaimana jika user tidak memilih gambar sama sekali? Kita butuh fallback default.
Solusi di PHP
Gunakan parameter ketiga di JSXBlock:
new JSXBlock("banner", true, array(
'fallbackImage' => get_theme_file_uri('/images/library-hero.jpg')
));Akses di JavaScript
// Data tersedia di window.banner.fallbackImage
wp.blocks.registerBlockType("ourBlockTheme/banner", {
attributes: {
imgURL: {
type: "string",
default: window.banner.fallbackImage // Fallback dari PHP
}
}
// ...
});Cara Kerja wp_localize_script
PHP (server) → JavaScript (client)
─────────────────────────────────────────────────────
get_theme_file_uri(...) → window.banner.fallbackImage
$data['fallbackImage'] → Tersedia di global scope JSFile PHP Render: banner.php
<?php
if (!isset($attributes['imgURL'])) {
$attributes['imgURL'] = get_theme_file_uri('/images/library-hero.jpg');
}
?>
<div class="page-banner">
<div class="page-banner__bg-image"
style="background-image: url('<?php echo esc_url($attributes['imgURL']); ?>');
background-position: center center;">
</div>
<div class="page-banner__content container">
<?php echo $content; ?>
</div>
</div>CSS Fix: Tambahkan
background-position: center centeragar gambar selalu terpusat.
Kesimpulan
| Komponen | Fungsi |
|---|---|
MediaUpload | UI untuk memilih gambar dari media library |
MediaUploadCheck | Wrapper — cek permission upload |
apiFetch | Fetch REST API WordPress (async) |
useEffect | Watch imageID → fetch URL gambar |
/wp/v2/media/{id} | Endpoint untuk detail media (termasuk custom sizes) |
wp_localize_script | Kirim data dari PHP ke JS (fallback image) |
isset() check | Di PHP render: gunakan fallback jika imgURL kosong |