f in x
Gutenberg Blocks Custom con React — Blocchi WordPress Che Fanno Guadagnare
> cd .. / HUB_EDITORIALE > Visualizza in Inglese
Sviluppo di siti web

Gutenberg Blocks Custom con React — Blocchi WordPress Che Fanno Guadagnare

[2026-06-23] Author: Ing. Calogero Bono

Il cliente ti chiede un layout che il block editor standard non regge. Sei bloccato. O imbottisci di HTML dentro un blocco «Custom HTML» — che poi si rompe al primo aggiornamento — o costruisci un blocco Gutenberg su misura. Noi abbiamo scelto la seconda strada, e non solo perché fa più figo. Perché un blocco custom fatto con React è l'unico modo per dare al tuo WordPress la libertà di design che serve a vendere, senza sacrificare performance e manutenibilità.

Perché sviluppare blocchi Gutenberg custom con React fa risparmiare tempo e soldi?

Ogni volta che usi un page builder o un blocco di terze parti, paghi un canone o accumuli debt tecnico. I blocchi custom, invece, li possiedi. Noi, di Meteora Web, partiamo dal conto economico del cliente: un blocco su misura costa una volta, poi rende per anni. Con React dentro Gutenberg ottieni componenti riutilizzabili, stato locale gestito con leve pronte (useState, useEffect) e un pannello di controllo che sembra un'app, non un form anni 2000.

Un esempio concreto: un cliente e-commerce aveva bisogno di un blocco per mostrare i prodotti in saldo con countdown. Con ACF e jQuery il risultato era lento e impossibile da tradurre. Abbiamo costruito un blocco Gutenberg custom in React: attributi per data scadenza, stile del countdown, numero di prodotti. Tempo di sviluppo: due giorni. Manutenzione: zero. Il sito ha caricato il 40% più veloce.

Sponsored Protocol

Differenza tra blocchi statici e dinamici

Un blocco statico salva l'HTML nel post_content. Veloce, ma poco flessibile. Un blocco dinamico (senza save, solo render_callback) genera l'output lato server. Noi usiamo i dinamici per tutto ciò che deve aggiornarsi senza re-salvare il post — es. ultimi articoli, prezzi in tempo reale. Per il blocco custom, invece, il save con JSX ti dà controllo totale sull'output e funziona con il recupero visivo.

Come strutturare un blocco Gutenberg custom con React passo per passo?

Partiamo dalla cartella. Dentro il tema (o plugin) crei blocks/nome-blocco/. Dentro ci metti: block.json (la dichiarazione ufficiale di WordPress — obbligatoria da WP 6.0), edit.js (componente React per l'editor), save.js (output frontend), style.scss, index.js (punto di ingresso).

// block.json
{
  "apiVersion": 3,
  "name": "meteora/testimonial",
  "title": "Testimonial",
  "category": "widgets",
  "icon": "format-quote",
  "attributes": {
    "quote": { "type": "string" },
    "author": { "type": "string" },
    "avatarURL": { "type": "string", "default": "" }
  },
  "supports": {
    "align": ["wide", "full"],
    "color": { "background": true, "text": true },
    "spacing": { "padding": true }
  },
  "editorScript": "file:./index.js",
  "style": "file:./style-index.css",
  "render": "file:./render.php"
}

Nota sul render.php: se il blocco è dinamico, qui scrivi il markup PHP. Noi lo usiamo quando i dati vengono dal database o da API esterne. Per blocchi puramente statici, lascia il save.js e ometti il render.

Sponsored Protocol

Registrare il blocco nel tema

Il modo più pulito: register_block_type( __DIR__ . '/blocks/testimonial' ); in functions.php. WordPress carica automaticamente il block.json e gli script React. Niente enqueue a mano.

// functions.php
add_action( 'init', function() {
    register_block_type( get_template_directory() . '/blocks/testimonial' );
} );

Come scrivere l'Edit component e il Save in React?

L'Edit è un componente React che riceve le props: attributes, setAttributes, clientId. Dentro usi i componenti di @wordpress/components: RichText per contenuti, MediaUpload per immagini, InspectorControls per le impostazioni laterali.

// edit.js
import { __ } from '@wordpress/i18n';
import { useBlockProps, RichText, MediaUpload, InspectorControls } from '@wordpress/block-editor';
import { Button, PanelBody, TextControl } from '@wordpress/components';

export default function Edit({ attributes, setAttributes }) {
    const { quote, author, avatarURL } = attributes;
    
    return (
        
setAttributes({ avatarURL: media.url })} render={({ open }) => ( )} />
{avatarURL && avatar} setAttributes({ quote: val })} placeholder={__('Scrivi la citazione…', 'meteora')} /> setAttributes({ author: val })} placeholder={__('Autore', 'meteora')} />
); }

Il Save per blocco statico restituisce JSX che diventa l'HTML finale. Attenzione: non usare componenti React qui — solo markup puro.

Sponsored Protocol

// save.js
import { useBlockProps, RichText } from '@wordpress/block-editor';

export default function save({ attributes }) {
    const { quote, author, avatarURL } = attributes;
    
    return (
        
{avatarURL && avatar} {quote &&

{quote}

} {author && {author}}
); }

Errore comune: mettere logiche di stato o effetti nel save. Il save deve essere puramente dichiarativo. Se hai bisogno di dati live, usa un blocco dinamico con render.php.

Come gestire dati dinamici e richieste API dentro un blocco Gutenberg?

Spesso il blocco deve mostrare dati da un CPT, da un'API esterna o da un cache. In edit usi useSelect per query WordPress lato editor (senza server). Esempio: recuperare gli ultimi 5 post.

Sponsored Protocol

import { useSelect } from '@wordpress/data';
import { useBlockProps } from '@wordpress/block-editor';

export default function LatestPostsEdit() {
    const posts = useSelect((select) => {
        return select('core').getEntityRecords('postType', 'post', {
            per_page: 5,
            _embed: true,
        });
    }, []);
    
    return (
        
{posts ? ( ) : (

Caricamento…

)}
); }

Per richieste a servizi esterni (es. listino prezzi da un ERP), meglio usare la store API di WordPress e un endpoint custom nel tema. Noi abbiamo integrato blocchi che leggono il catalogo da API REST esterne — con caching lato server per evitare rallentamenti.

Come testare e ottimizzare un blocco Gutenberg custom?

Tooling: @wordpress/scripts fornisce webpack già configurato con JSX, SCSS e minification. Lancialo con npm start per sviluppo e npm run build per produzione. Noi aggiungiamo sempre eslint e prettier per codice pulito.

Sponsored Protocol

Performance: evita di caricare librerie React inutili. Il core WordPress include già React e wp-element. Il tuo bundle deve essere piccolo. Controlla con npm run build e verifica la dimensione del file.

Sicurezza: sanifica sempre gli attributi lato server. In render.php usa esc_html, esc_url. Non fidarti dell'input salvato. Lo vediamo spesso: blocchi custom che espongono XSS perché il testo non è scappato.

Accessibilità: usa RichText che gestisce già aria-label e focus. Aggiungi role e aria-* dove serve. Google penalizza i siti con blocchi inaccessibili? No, ma gli utenti sì.

Cosa fare adesso?

  1. Valuta se ti serve un blocco custom. Se il design richiede interazioni uniche o dati live, fallo. Se puoi usare i blocchi core (Cover, Columns, Group) con qualche CSS, risparmi tempo.
  2. Scarica @wordpress/create-block per generare lo scaffold. Comando: npx @wordpress/create-block meteora-testimonial. Ti dà tutto pronto.
  3. Leggi la documentazione ufficiale su WordPress Block Editor Handbook.
  4. Controlla i blocchi esistenti — spesso un blocco di terze parti può essere esteso con filtri. Noi preferiamo partire da zero per avere controllo totale, ma non è sempre necessario.
  5. Contattaci se vuoi che sviluppiamo blocchi su misura per la tua PMI. Partiamo dal problema, non dalla tecnologia. Vedi la nostra pagina dedicata a WordPress Avanzato.
Ing. Calogero Bono

> AUTHOR_EXTRACTED

Ing. Calogero Bono

Ingegnere Informatico, co-fondatore di Meteora Web. Esperto in architetture software, sicurezza informatica e sviluppo sistemi scalabili.
[ Read Full Dossier ]

> METEORA_WEB // WEB AGENCY

Costruiamo la presenza digitale che la tua azienda merita.

Siti web, social, pubblicità online, e-commerce e hosting performante: ingegnerizzati con metodo da ingegneri informatici a Sciacca, per tutta Italia.

> MW_JOURNAL

> READ_ALL()