React come funziona - Gestire lo Stato del componente
Continuando dall'esempio precedente vediamo come gestire lo stato di un componente React, realizziamo un semplice orologio.
Il seguente esempio visualizza l'ora attuale:
Nel costruttore dichiaro l'oggetto che manterrà lo stato this.state e nel metodo render ritorno l'html che rappresenta il componente.
Eseguendo questo esempio si nota subito che nonostante la funzione tick venga richiamata ogni secondo da setInterval la data non cambia. Questo perchè non abbiamo notificato a React che lo stato è cambiato.
Per visualizzare l'ora aggiornata dobbiamo modificare il codice e utilizzare il metodo this.setState per notificare il cambiamento che, a sua volta, scatena l'aggiornamento del componente, questa è la nuova versione:
in questo esempio ho introdotto un po' di cose nuove:
Le cose di cui ricordarsi sono:
Vedi anche Components and Props, State and Lifecycle e React come funziona - Gestire gli eventi
Il seguente esempio visualizza l'ora attuale:
React JSX
class Clock extends React.Component {
//aggiungo lo stato locale al componente
constructor(props) {
super(props);
//creo l'oggetto che rappresenta lo stato del componente
this.state = {date: new Date()};
}
//nessuna virgola di terminazione
render() {
return (
<div>
<h1>Orologio</h1>
<h2>sono le {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
function tick() {
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
}
//la data non cambia ad ogni richiamo (1s)
setInterval(tick, 1000);
per funzionare deve essere utilizzato la base html dell'esempio precedente
La prima cosa da notare è che l'oggetto è stato creato tramite la keyword class ed estende React.Component mentre nell'esempio precedente avevo usato function.Nel costruttore dichiaro l'oggetto che manterrà lo stato this.state e nel metodo render ritorno l'html che rappresenta il componente.
Eseguendo questo esempio si nota subito che nonostante la funzione tick venga richiamata ogni secondo da setInterval la data non cambia. Questo perchè non abbiamo notificato a React che lo stato è cambiato.
Per visualizzare l'ora aggiornata dobbiamo modificare il codice e utilizzare il metodo this.setState per notificare il cambiamento che, a sua volta, scatena l'aggiornamento del componente, questa è la nuova versione:
React JSX
class Clock extends React.Component {
constructor(props) {
super(props);
this.state = { //this.state has a special meaning
date: new Date(),
propTemp: 1 // non usato, non viene modificato da setState
};
}
componentDidMount() {
this.timerID = setInterval(
() => this.tick(), // funzione anonima che richiama "tick"
1000 // 1 secondo
);
}
componentWillUnmount() {
clearInterval(this.timerID);
}
tick() {
this.setState({
date: new Date()
});
}
render() {
return (
<div>
<h1>Orologio</h1>
<h2>sono le {this.state.date.toLocaleTimeString()}.</h2>
</div>
);
}
}
ReactDOM.render(
<Clock />,
document.getElementById('root')
);
- l'oggetto è stato creato tramite la keyword class (ES6)
- la classe deve estendere (extends) l'oggetto React.Component
- al costruttore deve essere passato l'oggetto props che conterrà gli eventuali valori assegnati agli attributi del tag dell'html
- il costruttore deve sempre richiamare il metodo super(props)
- this.state: mantiene lo stato del componente ed ha un significato speciale per React
- componentDidMount: eseguito dopo che è stato invocato render e dopo che il DOM è stato aggiornato
- componentWillUnmount: invocato quando il componente è rimosso dal DOM
- this.setState: per notificare il cambiamento dello stato e scatenare il rendering (solo le parti modificate vengono aggiornate nel DOM)
- la funzione tick è un metodo dell'oggetto Clock e non necessita della keyword function
Le cose di cui ricordarsi sono:
- non modificare mai lo stato del componente direttamente, è ammesso solo nel costruttore, usare this.setState
- l'aggiornamento dello stato può essere asincrono, per fare aggiornamenti multipli usare
this.setState( (prevState, props) => {
return { counter: prevState.counter + props.increment };
}); - gli aggiornamenti dello stato vengono combinati (merge) con i valori esistenti, questo vuol dire che posso aggiornare anche una sola proprietà non necessariamente tutto l'oggetto (se la proprietà modificata è un oggetto va passato un nuovo oggetto modificato)
- un componente può passare lo stato a un componente "interno", il componente interno non deve sapere da dove arriva lo stato. Viene definita top-down o unidirectional data flow
- lo stato va mentenuto in un unico punto, tipicamente il componente root della gerarchia
Vedi anche Components and Props, State and Lifecycle e React come funziona - Gestire gli eventi