Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

React, l'interfaccia utente costruita componente su componente

Sfruttare la libreria JavaScript creata da Facebook e Instagram, per creare interfacce utente complesse tramite la loro suddivisione in componenti
Sfruttare la libreria JavaScript creata da Facebook e Instagram, per creare interfacce utente complesse tramite la loro suddivisione in componenti
Link copiato negli appunti

React è una libreria JavaScript, creata da Facebook e Instagram (e utilizzata anche nei due social network), che consente di creare interfacce utente complesse tramite la loro suddivisione in componenti.

L'idea è quella di supportare i team di sviluppo che lavorano su progetti di dimensioni medio/grandi o di una certa complessità, agevolando la creazione, la manutenzione e l'aggiornamento della UI.

React è stato progettato per essere semplice da usare e supporta la definizione di modelli HTML per ciascun componente tramite un approccio dichiarativo, che viene aggiornato automaticamente dal "core" della libreria nel momento in cui cambiano i dati dello stato su cui si basa il modello stesso.

In questo articolo esaminiamo le caratteristiche che fanno di React una libreria unica nel suo genere.

Sviluppo per componenti

Ogni componente è in grado di definire il proprio aspetto (ossia il markup), mantenere un proprio stato e racchiudere una parte di logica.

Per aiutare a comprendere meglio il principio di funzionamento, un componente non è molto diverso da quello adottato in altri ambienti dove l'interfaccia si esprime tramite l'uso di controlli, ovvero classi specializzate che eseguono il rendering di una porzione dell'interfaccia complessiva, contengono campi per mantenere i valori che costituiscono lo stato e all'occorrenza metodi per l'implementazione di funzionalità usate internamente o richiamabili dall'esterno, se necessari.

Ciascun componente incapsula tutto ciò di cui ha bisogno, ed è pertanto completamente isolabile, riutilizzabile e testabile, in ottemperanza ai principi di corretta suddivisione delle responsabilità.

Tutto ciò può avvenire sul server, tramite il supporto a Node.js, oppure all'interno del browser, sul client, permettendo a interfacce utente anche molto complesse di reagire in tempo reale.

Scaricare React

Per utilizzare il framework, occorre innanzitutto scaricare i file della libreria dalla pagina dei download del sito ufficiale.

Possiamo scaricare individualmente i file sorgenti della libreria, oppure un "bundle" completo in formato ZIP contenente tutti i file necessari. Date le dimensioni estremamente contenute del pacchetto, possiamo optare per quest'ultima soluzione: sarà possibile estrarre e copiare i file necessari in base alla necessità.

La versione disponibile al momento della redazione di questo articolo è la 0.10.0; tuttavia, trattando concetti di base, ciò che andremo a vedere dovrebbe applicarsi senza alcun problema anche alle versioni successive.

Inizializzare la libreria

Per utilizzare la libreria sulle nostre pagina Web, aggiungiamo nel markup i riferimenti ai file JavaScript (che si trovano nella cartella build dell'archivio che abbiamo scaricato).

In alternativa, possiamo referenziare gli script disponibili su CDN all'indirizzo http://fb.me. Vediamo un esempio:

Qui di seguito è riportato un esempio della struttura base di una pagina che fa uso di React:

<!DOCTYPE html>
<html>
<head>
<title>Ciao React!</title> 
<!-- Import della libreria React -->
<script src="http://fb.me/react-0.10.0.js"></script>
<script src="http://fb.me/JSXTransformer-0.10.0.js"></script> 
</head>
<body>
<div id="example"></div>
<script type="text/jsx">
/**
* @jsx React.DOM
*/ 
// ** Il codice va qui! **
</script>
</body>
</html>

Noterete subito che il tag <script> indica un content type particolare: text/jsx. A cosa si riferisce? Vediamolo subito.

La sintassi JSX

Come abbiamo già detto, i componenti creati con React sono in grado di generare il markup HTML che li rappresenta visualmente nella pagina attraverso l'applicazione di un template, che generalmente varia in base al modello dei dati e allo stato del componente, espresso tramite codice JavaScript.

I creatori di React hanno voluto agevolare il lavoro di scrittura del template adottando JSX, una sintassi che consente di mescolare codice e funzioni JavaScript al markup HTML.

Ad esempio, per generare un link all'interno del nostro componente React, possiamo scrivere qualcosa di simile a questo:

React.renderComponent(
	return React.DOM.a({href: 'http://facebook.github.io/react/'}, 'Ciao React!');
);

È comprensibile che per tag HTML più complessi e articolati, il codice tenda a diventare intricato e poco leggibile; utilizzando invece JSX, possiamo rappresentare il template in questo modo, semplificandone la scrittura:

React.renderComponent(
	<a href="http://facebook.github.io/react/">Ciao React!</a>
);

Il compilatore "live" di JSX, attivato importando il file sorgente JSXTransformer.js, interpreta questi frammenti di markup e li trasforma nel codice corrispondente in linguaggio JavaScript.

Un avvertimento importante: oltre a specificare il tipo di contenuto "text/jsx" nel tag <script>, non bisogna dimenticare di aggiungere in testa al codice il commento che indica al compilatore JSX di "trasformarlo", altrimenti esso non verrà preso in considerazione:

/** * @jsx React.DOM */

Oltre ai tag HTML standard, la sintassi JSX si potrà utilizzare anche per esprimere nomi di componenti React creati da noi, valorizzando le proprietà del componente stesso.

Pur essendo JSX un ottimo strumento per lavorare con React, poiché consente di scrivere in modo fluido e familiare il codice HTML della nostra interfaccia, il suo utilizzo non è obbligatorio. Tuttavia continueremo a farne uso anche nei prossimi esempi per acquisire maggior confidenza con questo strumento.

Nella seconda parte dell'articolo vedremo come creare i componenti.

Creare componenti con React

Quando si progetta una interfaccia utente, è necessario immaginarla come il risultato della composizione di tanti elementi, partendo dal più grande che al suo interno contiene via via quelli più piccoli. Vediamo quindi come creare i componenti, gli elementi fondamentali da combinare per realizzare l'interfaccia.

Rendering di un componente

È grazie a JavaScript che possiamo definire la struttura di un componente, nella quale indichiamo:

  1. il DOM da generare per rappresentarlo sulla pagina (usando opzionalmente la sintassi JSX);
  2. il comportamento, ovvero come esso reagisce alle azioni dell'utente.

Inoltre il componente React rappresenta una vera e propria "macchina a stati", ossia indica le variabili che esprimono il suo stato iniziale che possono essere alterate.

Un sempice esempio ci sarà d'aiuto: realizziamo il più semplice dei componenti, il classico "Hello world".

var HelloReact = React.createClass({ 
	render : function() {
		return <div>Hello React!</div>;
	}
});

La funzione React.createClass consente di dichiarare un nuovo componente e di definire tutte le sue caratteristiche.

Nell'esempio, la proprietà render dell'oggetto passato viene valorizzata con una funzione in grado di restituire il markup che rappresenta il componente sulla pagina: in questo caso, apparirà un semplice <div> con la scritta "Hello React!".

Nella logica della funzione render(), la mescolanza di JavaScript e HTML viene resa possibile dalla sintassi JSX, di cui abbiamo già parlato. Siccome la funzione potrà avere sempre uno e un solo valore di ritorno, questa scrittura non è possibile:

var HelloReact = React.createClass({
	render : function() {
		return
		<p>Questo è il primo esempio</p>
		<div>Hello React!</div>;
	}
});

Ogni tag viene tradotto da JSX in un oggetto, quindi nel codice sopra ne stiamo restituendo due. Per poter restituire componenti multipli, è sufficiente che questi siano inseriti all'interno di un unico "contenitore", dove possiamo metterne quanti vogliamo, come illustrato in questo esempio:

var HelloWorld = React.createClass({ 
	render : function() {
		return <div><p>Questo è il primo esempio:</p> <span>Hello React!</span></div>;
	}
});

Per visualizzare il componente "HelloWorld" che abbiamo appena creato all'interno della nostra pagina, occorre richiamare la funzione React.renderComponent:

React.renderComponent(
	<HelloWorld />,
	document.body
);

La funzione renderComponent() prende due parametri: il componente React che deve essere visualizzato nella pagina e l'elemento del DOM che lo ospiterà (in questo caso, si tratta del <body> della pagina); anche qui, il componente può essere specificato utilizzando ancora la sintassi JSX.

Proprietà e stato di un componente

Ogni componente rappresenta un modello replicabile di markup che deve essere inserito nella pagina per fungere da vista per un singolo dato o un insieme di dati.

Nella fase di creazione di un componente tramite la funzione React.createClass(), possiamo definire un insieme di proprietà per passare al componente valori da inserire all'interno del template HTML generato in fase di rendering, oppure per influenzarne la logica interna di funzionamento. I valori delle proprietà sono contenuti nel campo props.

Ecco il codice di esempio di un componente che visualizza un saluto all'utente consentendo di specificare dall'esterno il nome della persona valorizzando la proprietà "name":

var GreetingMessage = React.createClass({ 
	render: function() {
		return <div>Ciao <strong>{this.props.name}</strong></div>;
	}
});

Questo è invece il codice che effettua il rendering del componente GreetingMessage valorizzando la proprietà:

React.renderComponent(<GreetingMessage name="Marco" />, document.body);

Una delle prerogative di React è quella di poter generare gli elementi del DOM in base ai dati specificati e, qualora essi subiscano un cambiamento, "reagire" aggiornandoli per riflettere tali cambiamenti. Tuttavia, le proprietà sono immutabili, ovvero non è possibile modificare i valori delle proprietà impostati inizialmente: per queste esigenze è possibile ricorrere allo stato del componente.

Analogamente alle proprietà, lo stato di un componente è un oggetto (memorizzato nel campo state) che contiene valori utilizzabili durante il rendering e modificabili all'occorrenza attraverso funzioni specifiche del framework che consentono a React di occuparsi - se necessario - dell'aggiornamento degli elementi del DOM legati al nuovo stato, nel modo più veloce e performante possibile.

Analizziamo il seguente esempio di codice che implementa un pulsante "Mi piace" e lo inserisce nel <body> della pagina:

/** @jsx React.DOM */ 
var LikeButton = React.createClass({ 
	getInitialState: function() {
		return {liked: false};
	}, 
	handleClick: function(event) {
		this.setState({liked: !this.state.liked});
	}, 
	render: function() {
		var text = this.state.liked ? 'piace' : 'NON piace';
		return (
			<p onClick={this.handleClick}>
			A te {text} questo esempio. Clicca per modificare.
			</p>
		);
	}
});

Oltre alla funzione render() già vista, possiamo notare la presenza della funzione getInitialState(), che ha lo scopo di restituire l'oggetto che rappresenta lo stato iniziale del componente; nell'esempio sopra, viene creato e restituito un oggetto che contiene un campo booleano, "like", che viene impostato a "true" se l'esempio ci piace oppure a "false" in caso contrario.

La funzione handleClick() è un callback che intercetta l'azione di clic con il mouse sul testo del componente per variarne lo stato: attraverso l'uso della funzione setState(), impostiamo i valori dello stato aggiornato del componente communtando il valore booleano del campo "liked" e informando contemporaneamente React della possibile necessità di aggiornare l'interfaccia rappresentata dal componente nella pagina.

La funzione render() restituisce l'elemento HTML (un semplice paragrafo <p>) da inserire nella pagina, utilizzando una dicitura differente in base alla preferenza espressa e memorizzata in una variabile temporanea ("text"); è presente inoltre l'associazione della funzione di callback handleClick() all'evento di clic sul paragrafo, affinché sia possibile intercettarlo eseguendo la commutazione del nostro apprezzamento.

Gestione degli eventi

La gestione degli eventi è una funzionalità imprescindibile per qualsiasi framework progettato per la creazione di applicazioni Web dinamiche e interattive, e ciò vale ovviamente anche per React.

Per rispondere alle azioni dell'utente, come abbiamo visto nell'esempio del "LikeButton", React consente di associare funzioni di callback agli eventi supportati dagli elementi HTML, specificandone il nome usando la convenzione cosiddetta "camelCase" (es. per l'evento onclick, si usa l'attributo onClick).

Anche se potrebbe sembrare da una prima lettura del codice, React non aggancia ogni funzione di callback al singolo elemento del DOM, bensì utilizza un proprio gestore unificato degli eventi che si verificano nella pagina (event listener), propagando l'esecuzione al callback appropriato in base all'azione specifica e all'elemento su cui è stata rilevata l'interazione.

Attraverso un meccanismo di mappatura interna delle funzioni di calback e a diverse ottimizzazioni, React garantisce una gestione efficiente, performante e ottimale degli eventi, semplificando inoltre la scrittura del codice che può essere fatta utilizzando le convenzioni abituali.

Un esempio completo

Per scoprire altre caratteristiche peculiari di React, dissezioniamo il codice della classica applicazione "Cose da fare" (To Do List), presente anche sul sito ufficiale (vedi "An Application").

Questa applicazione costituisce uno degli esempi dimostrativi a cui si ricorre più spesso per illustrare le caratteristiche dei framework come React e affini e permette di compilare una lista di cose da fare inserendo il testo in una casella e premendo un pulsante per aggiungere l'elemento all'elenco.

Per implementare l'interfaccia utente con React, dobbiamo scomporla nelle sue parti fondamentali.

Iniziamo con la creazione del componente che mostra le "cose da fare" come lista non ordinata usando dei punti elenco:

var TodoList = React.createClass({ 
	render: function() {
		var createItem = function(itemText) {
			return <li>{itemText}</li>;
		}; 
		return <ul>{this.props.items.map(createItem)}</ul>;
	}
});

Il codice definisce il componente "TodoList" e implementa la funzione render() per generare il markup corrispondente; la funzione di supporto createItem() produce il markup di una singola "cosa da fare" e viene richiamata per ogni elemento presente nella lista delle attività; la lista è memorizzata nella proprietà items del componente.

Vediamo il codice del componente che costituisce l'applicazione nella sua interezza e che assembla tutti i componenti in un unico contenitore:

var TodoApp = React.createClass({ 
	getInitialState: function() {
		return {items: [], text: ''};
	}, 
	onChange: function(e) {
		this.setState({text: e.target.value});
	}, 
	handleSubmit: function(e) {
		e.preventDefault();
		var nextItems = this.state.items.concat([this.state.text]);
		var nextText = '';
		this.setState({items: nextItems, text: nextText});
	}, 
	render: function() {
		return (
			<div>
			<h3>TODO</h3>
			<TodoList items={this.state.items} />
			<form onSubmit={this.handleSubmit}>
				<input onChange={this.onChange} value={this.state.text} />
				<button>{'Add #' + (this.state.items.length + 1)}</button>
			</form>
			</div>
		);
	}
});

La funzione getInitialState() imposta i valori iniziali dell'interfaccia, ossia predispone un array vuoto di attività da fare e il testo predefinito della descrizione. Nel metodo render() troviamo la dichiarazione del componente <TodoList> a cui viene passata la lista degli elementi (che verrà memorizzata nella proprietà relativa); ogni cambiamento alla lista scatenerà quindi l'azione di React che aggiornerà il DOM del componente sulla pagina.

È presente inoltre la dichiarazione del form per l'inserimento di nuove attività, con l'aggancio dei callback per l'evento onSubmit - per intercettare l'invio (submit, appunto) del form - e dell'evento onChange per la casella di testo in cui inseriamo la descrizione - poiché il suo valore deve essere copiato nelle variabili di stato dei componenti React e aggiornato di conseguenza se questo viene modificato tramite codice.

Le funzioni di callback hanno il semplice compito di aggiornare lo stato del componente, delegando a React il compito di intervenire sul DOM per riflettere le modifiche sui controlli nella pagina nel modo più veloce possibile.

Infine, per visualizzare il controllo contenitore dell'intera applicazione nel <body> della pagina basta scrivere:

React.renderComponent(<TodoApp />, document.body);

Avremmo potuto scegliere qualsiasi altro elemento contenitore invece di <body>elemento, anche un <div>, usando la funzione getElementById().

È possibile visualizzare un esempio funzionante dell'applicazione e più ricco di funzionalità (con possibilità di contrassegnare le attività svolte e rimuovere quelle completate) in questa pagina.

Conclusioni

React offre paradigma che ci aiuta a frazionare gli elementi che compongono l'interfaccia utente in componenti riutilizzabili. Grazie a un numero ristretto di funzioni e alla sintassi JSX agevola la scrittura della logica JavaScript e del markup.

La gestione dell'interfaccia è l'unica missione di React: il framework non è stato appesantito inutilmente da dipendenze indesiderate e non necessarie (come ad esempio servizi per chiamate REST, widget o altre aggiunte ed estensioni), poiché è stato progettato per essere snello ed estremamente performante nell'intervenire sul DOM, offrendo allo sviluppatore massima apertura e libertà di scelta su quali librerie accessorie adottare per svolgere tutti quei compiti che non sono legati strettamente alla realizzazione dell'interfaccia.

Esiste già tuttavia un nutrito insieme di soluzioni e add-on disponibili con adeguata documentazione per le esigenze più frequenti di integrazione ed estensione con altri framework e librerie che rendono React un ottimo strumento per la creazione di Web Application.

Grazie alle basi fornite da questo articolo, potete approfondire tutte le altre funzionalità della libreria di sicuro interesse consultando la documentazione completa e gli esempi avanzati.

Ti consigliamo anche