The following is the HTML.
<script src=".3284-6/12624079_897774290317920_1379776191_n.js"></script>
<script src=".3284-6/12624052_751451571621845_431133942_n.js"></script>
<script src=".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>
The following is the Javscript
var SizeEnum = {
SMALL: 1,
MEDIUM: 2,
LARGE: 3
};
var Board = React.createClass({
getInitialState: function() {
return {
size: SizeEnum.MEDIUM
};
},
ponentWillMount: 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"));
And some CSS
#game-container {
position: relative;
margin-top: 32px;
border: 1px solid black;
width: 100%;
}
What I want is that when the appropriate button is clicked, the Board ponent be resized to the appropriate size.
I've tried doing it like this
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"));
}
}
But it doesn't work.
The following is the HTML.
<script src="https://fbcdn-dragon-a.akamaihd/hphotos-ak-xtp1/t39.3284-6/12624079_897774290317920_1379776191_n.js"></script>
<script src="https://fbcdn-dragon-a.akamaihd/hphotos-ak-xfp1/t39.3284-6/12624052_751451571621845_431133942_n.js"></script>
<script src="https://cdnjs.cloudflare./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>
The following is the Javscript
var SizeEnum = {
SMALL: 1,
MEDIUM: 2,
LARGE: 3
};
var Board = React.createClass({
getInitialState: function() {
return {
size: SizeEnum.MEDIUM
};
},
ponentWillMount: 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"));
And some CSS
#game-container {
position: relative;
margin-top: 32px;
border: 1px solid black;
width: 100%;
}
What I want is that when the appropriate button is clicked, the Board ponent be resized to the appropriate size.
I've tried doing it like this
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"));
}
}
But it doesn't work.
Share Improve this question edited Mar 23, 2016 at 16:30 dorado asked Mar 23, 2016 at 16:14 doradodorado 1,5251 gold badge16 silver badges38 bronze badges 5- 2 Why do you have html with buttons in it? React is ponent based and all "html" should be in JSX within a render function – erichardson30 Commented Mar 23, 2016 at 16:31
- agree with the above, those buttons should be ponents, then this is pretty simple – omarjmh Commented Mar 23, 2016 at 16:34
- Ok so I make the buttons ponents.. then? – dorado Commented Mar 23, 2016 at 16:35
- @dorado after making buttons the ponents, you should be able to attach an onClick function to them which in that onClick can change the state – erichardson30 Commented Mar 23, 2016 at 16:37
- so that onClick on the button will be able to change the sate of the board? – dorado Commented Mar 23, 2016 at 16:37
4 Answers
Reset to default 4You can't set the state of a React ponent like that. And the ponent should be responsible for setting its own state.
Inside your Board ponent, set up event listeners in ponentDidMount. The best solution would be to let the buttons be part of the React application, but that's beyond the scope of this question. So let's say that the buttons are not part of the React application, then do something like this:
var Board = React.createClass({
...
...
ponentDidMount: 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(){
...
...
}
});
Then just move all that ponentWillMount style stuff to the render
function.
Update
Fiddle: https://jsfiddle/dannyjolie/r525ux66/
You are taking the wrong approach. The hardest part about react is "Thinking in React." If you want things to work properly, the notion of reaching into the DOM directly, like you are doing with document.getElementById, is off the table.
The simplest way for you to get started is to render your button inside the render function of your Board ponent. Then you can put a click handler inside the Board ponent to set the state.
This should get you started:
handleClick: function (event) {
this.setState({ size: SizeEnum.SMALL });
},
render: function() {
return (
<div>
<div style = { this.style}></div>
<input type="button" onClick={this.handleClick}
</div>
)
}
Once you get this working, if you want to separate your button from your button, then you will want to look into using a Flux implementation to pass state from ponent to ponent.
You should not change state of React ponent directly. Use setState function instead. When you call setState React will re-render poment.
Add new function setSize to your Board poment:
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'
}
}
},
ponentWillMount: 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);
}
}
This is an anti pattern though this is the right way to achieve what you are looking for.
Since ReactDOM.render returns an instance of the ponent that is rendered, you can use that and update it's state.
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});
}
}
The right way to do this, is to make buttons ponents of Board and attach event handlers on them eg :
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
});
}
})