2016-03-23 1 views
6

Quanto segue è l'HTML.Modifica stato componente sul pulsante clic

<script src="https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-xtp1/t39.3284-6/12624079_897774290317920_1379776191_n.js"></script> 
<script src="https://fbcdn-dragon-a.akamaihd.net/hphotos-ak-xfp1/t39.3284-6/12624052_751451571621845_431133942_n.js"></script> 


<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.24/browser.min.js"></script> 

<div class="row" id="container"> 
    <div class="controls"> 
    <span class="" id="controls-size">Size : 
     <button id="controls-size-small">SMALL</button> 
     <button id="controls-size-med">MEDIUM</button> 
     <button id="controls-size-large">LARGE</button> 
    </span> 

    </div> 
    <div id="game-container"> 
    </div> 
</div> 

che segue è la javscript

var SizeEnum = { 
    SMALL: 1, 
    MEDIUM: 2, 
    LARGE: 3 
}; 

var Board = React.createClass({ 
     getInitialState: function() { 
     return { 
      size: SizeEnum.MEDIUM 
     }; 
     }, 

     componentWillMount: function() { 
     if (this.state.size == SizeEnum.SMALL) { 
      this.style = { 
      width: 600 + 'px', 
      height: 320 + 'px', 
      margin: 'auto', 
      border: '2px solid red' 
      } 
     } else if (this.state.size == SizeEnum.MEDIUM) { 
      this.style = { 
      width: 700 + 'px', 
      height: 500 + 'px', 
      margin: 'auto', 
      border: '2px solid red' 
      } 
     } else if (this.state.size == SizeEnum.LARGE) { 
      this.style = { 
      width: 900 + 'px', 
      height: 720 + 'px', 
      margin: 'auto', 
      border: '2px solid red' 
      } 
     } 
     }, 

     render: function() { 
      return (< div style = { 
      this.style 
      } > < /div> 
    ) 
    } 

}); 

ReactDOM.render(<Board/> , document.getElementById("game-container")); 

E alcuni CSS

#game-container { 
    position: relative; 
    margin-top: 32px; 
    border: 1px solid black; 
    width: 100%; 
} 

Quello che voglio è che quando l'apposito pulsante viene cliccato, il componente Consiglio essere ridimensionato alla dimensione appropriata .

Ho provato a farlo in questo modo

var board = ReactDOM.render(<Board />, document.getElementById("game-container")); 

document.getElementById("controls-size-small").onclick = changeBoardSize; 
document.getElementById("controls-size-med").onclick = changeBoardSize; 
document.getElementById("controls-size-large").onclick = changeBoardSize; 

function changeBoardSize(event) { 
    var etid = event.target.id; 
    console.log(etid); 
    if (etid == "controls-size-small") { 
     // method 1 
     board.state.size = SizeEnum.SMALL; 
    } else if (etid == "controls-size-med") { 
     // method 2 
     board.state.size = SizeEnum.MEDIUM; 
     ReactDOM.render(<Board />, document.getElementById("game-container")); 
    } else if (etid == "controls-size-small") { 
     // method 3 
     board.setState({size: SizeEnum.SMALL}); 
     ReactDOM.render(<Board />, document.getElementById("game-container")); 
    } 
} 

Ma non funziona.

+1

Perché devi html con bottoni in esso? React è basato su componenti e tutto "html" dovrebbe essere in JSX all'interno di una funzione di rendering – erichardson30

+0

d'accordo con quanto sopra, quei pulsanti dovrebbero essere componenti, quindi questo è piuttosto semplice – JordanHendrix

+0

Ok quindi faccio i componenti dei pulsanti .. allora? – dorado

risposta

3

Non è possibile impostare lo stato di un componente React come quello. E il componente dovrebbe essere responsabile dell'impostazione del proprio stato.

All'interno del componente Board, impostare i listener di eventi in componentDidMount. La soluzione migliore sarebbe lasciare che i pulsanti facciano parte dell'applicazione React, ma questo va oltre lo scopo di questa domanda. Quindi diciamo che i pulsanti non fanno parte dell'applicazione Reagire, quindi fare qualcosa di simile:

var Board = React.createClass({ 
    ... 
    ... 
    componentDidMount: function(){ 
    var that = this; 
    document.getElementById("controls-size-small").addEventListener('click', that.changeBoardSize, false); 
    document.getElementById("controls-size-med").addEventListener('click', that.changeBoardSize, false); 
    document.getElementById("controls-size-large").addEventListener('click', that.changeBoardSize, false); 
    } 

    changeBoardSize: function(e){ 
    /* get the element id and do the enum things here */ 
    this.setState({ 
     size: newSize 
    }); 
    } 
    render: function(){ 
    ... 
    ... 
    } 
}); 

Poi basta spostare tutta quella roba stile componentWillMount alla funzione render.

Aggiornamento

Fiddle: https://jsfiddle.net/dannyjolie/r525ux66/

+0

I pulsanti sono fondamentali per lo scopo di questa domanda. Il rendering degli elementi dell'interfaccia utente in modo tale che possano interagire con lo stato React è fondamentale per comprendere e utilizzare React. –

+1

Assolutamente, e negli scenari più comuni, sono d'accordo. Ma nel mondo reale, con project manager e diversi pezzi di codice che vanno oltre il tuo controllo giocando insieme, ci saranno delle eccezioni alla regola. E poiché OP ha presentato il problema con i pulsanti all'esterno dell'applicazione, ecco una delle possibili soluzioni. – dannyjolie

+0

@dannyjolie Questa sembra un'opzione lucrativa, ma non sembra funzionare – dorado

0

Questo è un anti modello anche se questo è il modo giusto per ottenere ciò che stai cercando.

Poiché ReactDOM.render restituisce un'istanza del componente che viene renderizzato, è possibile utilizzarlo e aggiornarlo.

function changeBoardSize(event) { 
     var etid = event.target.id; 
     console.log(etid); 
     if (etid == "controls-size-small") {  
      board.setState({size: SizeEnum.SMALL}); 
     } else if (etid == "controls-size-med") { 
      board.setState({size: SizeEnum.MEDIUM});  
     } else if (etid == "controls-size-small") { 
      board.setState({size: SizeEnum.LARGE}); 
     } 
    } 

Il modo giusto per fare questo, è quello di rendere i pulsanti componenti del Consiglio e allegare i gestori di eventi su di loro per esempio:

var Board = React.createClass({ 
     getInitialState: function() { 
     return { 
      size: SizeEnum.MEDIUM 
     }; 
     }, 
     render: function() { 
     return (
     <div> 
      <a href="#" onClick={this.onSizeChangeClick.bind(this, SizeEnum.SMALL)}>Small</a> 
      <a href="#" onClick={this.onSizeChangeClick.bind(this, SizeEnum.MEDIUM)}>Medium</a> 
      <a href="#" onClick={this.onSizeChangeClick.bind(this, SizeEnum.LARGE)}>Large</a> 
     </div> 
     ) 
     }, 

     onSizeChangeClick: function(size, event){ 
     event.preventDefault(); 
     this.setState({ 
      size: size 
     }); 
     } 
}) 
+0

Come potete vedere, ho già provato questo metodo sopra 3 ma non funziona. – dorado

+0

@dorado Che metodo hai provato, puoi mandarmi un plunker? – Burimi

+0

Interessante. Non mi sono reso conto che il risultato di ReactDom.render ti consentirà di impostareState su quel componente. Ho imparato qualcosa di nuovo! Ad ogni modo, resto ancora nella mia risposta che è più Reattivo tenere tutto in React. –

2

si sta prendendo l'approccio sbagliato. La parte più difficile della reazione è "Pensare in Reagire". Se vuoi che le cose funzionino correttamente, la nozione di raggiungere direttamente il DOM, come stai facendo con document.getElementById, è fuori dal tavolo.

Il modo più semplice per iniziare è il rendering del pulsante all'interno della funzione di rendering del componente Board. Quindi puoi inserire un gestore di clic all'interno del componente Board per impostare lo stato.

Questo dovrebbe iniziare:

handleClick: function (event) { 
     this.setState({ size: SizeEnum.SMALL }); 
    }, 
    render: function() { 
       return ( 
        <div> 
         <div style = { this.style}></div> 
         <input type="button" onClick={this.handleClick} 
        </div> 
      ) 
    } 

Dopo aver ottenuto questo lavoro, se si vuole separare il pulsante dal pulsante, allora si dovrà considerare di usare un'implementazione Flux passare stato dal componente al componente.

1

Si consiglia di non cambiare lo stato di Reagire direttamente componente. Utilizzare invece la funzione setState.Quando chiami setState, React esegue nuovamente il rendering del compoment.

Aggiungi nuova funzione setSize al compoment Consiglio:

var Board = React.createClass({ 
     getInitialState: function() { 
      return { 
      size: SizeEnum.MEDIUM 
     }; 
    }, 
    setSize: function(size) { 
     this._setStyle(size); 
     this.setState({size: size}); 
    }, 
    _setStyle: fiunction(size) { 
     if (size == SizeEnum.SMALL) { 
      this.style = { 
       width: 600 + 'px', 
       height: 320 + 'px', 
       margin: 'auto', 
       border: '2px solid red' 
      } 
     } else if (size == SizeEnum.MEDIUM) { 
      this.style = { 
       width: 700 + 'px', 
       height: 500 + 'px', 
       margin: 'auto', 
       border: '2px solid red' 
      } 
     } else if (this.state.size == SizeEnum.LARGE) { 
      this.style = { 
       width: 900 + 'px', 
       height: 720 + 'px', 
       margin: 'auto', 
       border: '2px solid red' 
      } 
     } 
    }, 
    componentWillMount: function() { 
     this._setStyle(this.state.size); 
    }, 
    // ................ 
    render: function() { 
     return (<div style={this.style}></div>) 
    } 
    }); 

    function changeBoardSize(event) { 
     var etid = event.target.id; 
     console.log(etid); 
     if (etid == "controls-size-small") { 
      board.setSize(SizeEnum.SMALL); 
     } else if (etid == "controls-size-med") { 
      board.setSize(SizeEnum.MEDIUM); 
     } else if (etid == "controls-size-small") { 
      board.setSize(SizeEnum.LARGE); 
     } 
     }