2016-04-16 20 views
5

Sto costruendo il Game of Life di React.js e mi trovo bloccato in una situazione scomoda: Ogni evento che ho impostato come onClick={ event } richiede 2 clic per l'esecuzione.Gli eventi React.js richiedono 2 click per eseguire

Permettetemi di descrivere più: Come si può vedere nel mio codice qui sotto, ho 2 pulsanti (un pulsante è quello di cambiare la dimensione del consiglio di amministrazione a 10 x 10, l'altro è quello di cambiare la velocità di l'intervallo).

Tutto va bene, tranne che quando faccio clic su questi due pulsanti, devo fare doppio clic per eseguire. Al primo clic, con React Developer Tool in Chrome, posso vedere che gli stati compresi width, height, speed sono stati modificati, ma lo stato board rimane invariato. Solo dopo il secondo clic, lo stato board viene modificato.

Chiunque può spiegare perché e mostrarmi come risolvere? Grazie

Ecco una parte del mio codice

var GameBoard = React.createClass({ 
    getInitialState: function() { 
     return { 
      width: 10, 
      height: 10, 
      board: [], 
      speed: 1000, 
     }; 
    }, 

    // clear the board to the initial state 
    clear: function(width, height) { 
     this.setState({ 
      width: width, 
      height: height, 
     }); 
     this.setSize(); 
     clearInterval(this.game); 
    }, 

    // set the size of the board 
    setSize: function() { 
     var board = []; 
     for (var i = 0; i < this.state.height; ++i) { 
      var line = []; 
      for (var j = 0; j < this.state.width; ++j) 
       line.push(0); 
      board.push(line); 
     } 
     this.setState({ 
      board: board 
     }); 
    }, 

    // start the game 
    start: function() { 
     this.game = setInterval(this.gameOfLife, this.state.speed); 
    }, 

    gameOfLife: function() { // game of life }, 

    // change the speed of the game 
    changeSpeed: function(speed) { 
     this.setState({ speed: speed }); 
     clearInterval(this.game); 
     this.start(); 
    }, 

    // change the size to 10 x 10 
    smallSize: function() { 
     this.clear(10, 10); 
    }, 

    render: function() { 
     return (
      <div className="game-board"> 
       <h1>Conway's Game of Life</h1> 
       <h2>Generation: { this.state.generation }</h2> 
       <div className="control"> 
        <button className="btn btn-default" onClick={ this.start }>Start</button> 

       </div> 

       <Environment board={ this.state.board } onChangeSquare = { this.onChangeSquare }/> 

       <div className="size"> 
        <h2>Size</h2> 
        <button className="btn btn-default" onClick={ this.smallSize }>Small (10 x 10)</button> 
       </div> 

       <div className="speed"> 
        <h2>Speed</h2> 
        <button className="btn btn-default" onClick={ this.changeSpeed.bind(this, 900) }>Slow</button> 
       </div> 
      </div> 
     ) 
    } 
}); 
+0

Hm, insicuro. Ma non è necessario "legare" tutte le funzioni che usano "questo" nei gestori di "onClick"? per esempio. 'smallSize' –

+0

Cosa intendi usando' bind' con 'smallSize'? Penso che questo metodo vada bene, tranne per il fatto che l'effetto di 'onClick' non funziona. – pexea12

+0

Hai 'this.clear.bind (this)' ma non 'this.smallSize.bind (this)' - anche se la seconda funzione sembra usare 'this' nella sua implementazione (' this.clear (10,10) '). Non dovrebbe causare il problema che stai vedendo, ma mi è sembrato un po 'strano –

risposta

0

La ragione è che lo stato di un componente non cambia immediatamente.

Nel metodo clear() si imposta lo stato di larghezza e altezza. Ma internamente quando reagiscono al metodo setSize() non saranno aggiornati immediatamente. Verranno aggiornati solo quando raggiungono il metodo di rendering.

Quando si fa clic sul pulsante la seconda volta gli stati sarebbero stati aggiornati correttamente. Ecco perché funziona in seconda istanza.

Una soluzione, per favore, non mantenere la larghezza e l'altezza come stato usarlo negli oggetti di scena. Mantieni il 10 * 10 come puntello predefinito separato e usalo nel metodo setSize.