web app cronometro

Un Cronometro realizzato con React JS

16 Gen 2020    Giacomo Marzolla    16 Gen 2020 05:27 pm

Prima piccola applicazione realizzata con React JS

Da poco mi sto approcciando all’utilizzo di React JS e vorrei condividere sul mio piccolissimo blog, la mia piccolissima esperienza con React e magari raccogliere l’esperienza di altri sviluppatori per implementare correzioni, migliore così da migliorarne lo sviluppo.

Con questo piccolo esercizio ho creato un piccolo cronometro, piccola premessa, nella gestione degli stati in React, sto utilizzando le classi e no le funzioni; come previsto nelle ultime versioni di React.

Dopo aver installato React, ho creato un componente che ho chiamato Timer, nominandolo timer.js.

Import React from 'react';
   class Timer extends React.Component {
}

All’interno del file timer.js, in cima al file con l’istruzione import React from ‘react’, possiamo utilizzare tutte le funzioni che React ci mette a disposizione, deve essere inserita come prima istruzione.

Successivamente creiamo la classe Timer estendendo quella Component già presente, aggiungo React.Component perché non ho passato Component nell’import.
Inserisco il metodo render() e ritorno un semplice div, per il momento. L’istruzione exxport default con il nome della classe, va inserita alla fine per poter richiamare il componente nel file principale App.js

Import React from 'react';
 class Timer extends React.Component {
        render(){
           return (
               <div className="timer">
               </div>
           );
   }
 } 
export default Timer;

Adesso importo il componente Timer in App, cliccando su file App.js, in cima al file dove ci sono già degli impor, ne aggiungo uno mio con la seguente istruzione (import Timer from ‘./timer’;). Inserisco il componente nella classe App per visualizzarlo nel frontend.

import React, { Component } from 'react';
import './App.css';
import Timer from './Timer';

function App() {
  return (
    <div className="App">
      <h1>Prima App in React</h1>
      <Timer/> <!-- componente aggiunto -->
    </div>
  );
}

export default App;

Torno nel file timer.js e all’interno della classe richiamo il metodo constructor(), questo metodo mi permette di ricevere l’oggetto con le proprietà che passiamo attraverso App, ma in questo esercizio non ho passato nessuna proprietà, diciamo che le passo per abitudine. Per poter accedere alle varie proprietà all’interno del metodo dobbiamo chiamare la classe parent “super(props);”

Import React from 'react';
 class Timer extends React.Component {
        constructor(props){
            super(props);
        }
        render(){
           return (
               <div className="timer">
               </div>
           );
   }
 } 
export default Timer;

Dopo aver salvato, mi credo tre metodi aggiuntivi all’interno della classe Timer  per gestire l’avvio, lo stop e l’azzeramento del cronometro. Ho inserito un console.log per capire se al click le funzioni vengono chiamate.

Import React from 'react';
 class Timer extends React.Component {
        constructor(props){
            super(props);
        }
      startTimer() {
        console.log(this.state.start);   
      }
      
      stopTimer() {
        //console.log("stop")
      }
    
      clearTimer() {
        //console.log("reset")
      }
        render(){
           return (
               <div className="timer">
               </div>
           );
   }
 } 
export default Timer;

Per richiamare queste tre funzioni useremo l’evento onClick, creo tre pulsanti con il tag html button e inserisco evento onClick con il nome della relativa funzione.

Import React from 'react';
 class Timer extends React.Component {
        constructor(props){
            super(props);
        }
      startTimer() {
        console.log(this.state.start);   
      }
      
      stopTimer() {
        //console.log("stop")
      }
    
      clearTimer() {
        //console.log("reset")
      }
        render(){
           return (
               <div className="timer">
                 <button onClick={this.startTimer}>Start</button>
                 <button onClick={this.stopTimer}>Stop</button>
                 <button onClick={this.clearTimer}>Clear</button>
               </div>
           );
   }
 } 
export default Timer;

C’è una piccola cosa da comprendere bene, ed è la questione dei this, per poter richiamare la funzione/metodo con l’evento onClick ho inserito il this.nomefunzione. Questo this deve puntare alla classe e no alla propria funzione, (ogni funzione ha il proprio this), per fare ciò devo bindare la funzione con il metodo bind all’interno del costruttore.

Import React from 'react';
 class Timer extends React.Component {
        constructor(props){
            super(props);
        
        //bindo la funzione
        this.startTimer = this.startTimer.bind(this);
        this.stopTimer = this.stopTimer.bind(this);
        this.clearTimer = this.clearTimer.bind(this);
      }
      startTimer() {
        console.log(this.state.start);   
      }
      
      stopTimer() {
        //console.log("stop")
      }
    
      clearTimer() {
        //console.log("reset")
      }
        render(){
           return (
               <div className="timer">
                 <button onClick={this.startTimer}>Start</button>
                 <button onClick={this.stopTimer}>Stop</button>
                 <button onClick={this.clearTimer}>Clear</button>
               </div>
           );
   }
 } 
export default Timer;

Adesso inizio a lavorare all’interno della funzione startTime, ma prima imposto gli stati di partenza nel costruttore, per iniziare imposterò il time e lo start a 0. Successivamente se mi serviranno altri stati, potrò aggiungerli tranquillamente.

Import React from 'react';
 class Timer extends React.Component {
        constructor(props){
            super(props);
        this.state = {
          time: 0,
          start: 0
        };
        //bindo la funzione
        this.startTimer = this.startTimer.bind(this);
        this.stopTimer = this.stopTimer.bind(this);
        this.clearTimer = this.clearTimer.bind(this);
      }
      startTimer() {
        console.log(this.state.start);   
      }
      
      stopTimer() {
        //console.log("stop")
      }
    
      clearTimer() {
        //console.log("reset")
      }
        render(){
           return (
               <div className="timer">
                 <button onClick={this.startTimer}>Start</button>
                 <button onClick={this.stopTimer}>Stop</button>
                 <button onClick={this.clearTimer}>Clear</button>
               </div>
           );
   }
 } 
export default Timer;

All’interno della funzione startTime, vado a modificare con i metodo setState lo stato assegnando a time lo stato (this.state.time) che la prima volta sarà 0; a start gli assegno la differenza tra Date.now() e lo stato di time, questo per permettere di riprendere il timer dopo lo stop.

Import React from 'react';
 class Timer extends React.Component {
        constructor(props){
            super(props);
        this.state = {
          time: 0,
          start: 0
        };
        //bindo la funzione
        this.startTimer = this.startTimer.bind(this);
        this.stopTimer = this.stopTimer.bind(this);
        this.clearTimer = this.clearTimer.bind(this);
      }
      startTimer() {
          time: this.state.time,
          start: Date.now() - this.state.time
        //console.log(this.state.start);   
      }
      
      stopTimer() {
        //console.log("stop")
      }
    
      clearTimer() {
        //console.log("reset")
      }
        render(){
           return (
               <div className="timer">
                 <button onClick={this.startTimer}>Start</button>
                 <button onClick={this.stopTimer}>Stop</button>
                 <button onClick={this.clearTimer}>Clear</button>
               </div>
           );
   }
 } 
export default Timer;

In this.timer inserisco il metodo setInterval, che mi permette di cambiare lo stato di time ad ogni secondo.

startTimer() {
        this.setState({
          isOn: true,
          time: this.state.time,
          start: Date.now() - this.state.time 
          // perché this.state.time = 0
        });
        
        this.timer = setInterval(() => this.setState({ 
          time: Date.now() - this.state.start 
        }), 1);
}
        

Nel metodo stopTimer, implemento la funzione clearInterval() che mi permette di fermare la funzione setInterval, passandogli timer.

stopTimer() {
        clearInterval(this.timer) 
      }

Nel metodo clearTime() invece setto lo stato di time a 0, utilizzando sempre il metodo setState().

clearTimer() {
        this.setState({time:0})
        //console.log("reset")
      }

Con questo la web app cronometro, molto light è terminata, probabilmente effettuerò un’ulteriore implementazione nella gestione dei button, vorrei far apparire e sparire i pulsanti se il cronometro è stato avviato o quando viene bloccato.