Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change component state on button click

The following is the HTML.

<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>

The following is the 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"));

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 component 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.

like image 993
dorado Avatar asked Mar 23 '16 16:03

dorado


People also ask

How do I update a component's state on click?

To update a component's state on click, add an onClick prop to an element and set it to a function. The function will be invoked every time the element is clicked, which allows us to update the component's state on click. Every time the user clicks on the button, the count state variable gets updated.

How to change the state of the component inside the function?

Then pass the function to the click handler and change the state of the component inside the function using setState. The setStatefunction used to change the stateof the component directly or with the callback approach as mentioned below.

How do I change the toggle state of a component?

Use Toggle State when you want to create components with interactive toggle behavior such as toggle, radio button, checbox and so on. In Design mode, click the + button next to the Default State of the Main Component in the Property Inspector, and select Toggle State.

How to change the state of a React component?

You should not change state of React component directly. Use setState function instead. When you call setState React will re-render compoment.


Video Answer


3 Answers

You can't set the state of a React component like that. And the component should be responsible for setting its own state.

Inside your Board component, set up event listeners in componentDidMount. 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({
  ...
  ...
  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(){
    ...
    ...
  }
});

Then just move all that componentWillMount style stuff to the render function.

Update

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

like image 80
dannyjolie Avatar answered Oct 11 '22 00:10

dannyjolie


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 component. Then you can put a click handler inside the Board component 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 component to component.

like image 22
Brian Shotola Avatar answered Oct 11 '22 01:10

Brian Shotola


You should not change state of React component directly. Use setState function instead. When you call setState React will re-render compoment.

Add new function setSize to your Board compoment:

    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);
        }
      }
like image 1
Володин Андрей Avatar answered Oct 11 '22 00:10

Володин Андрей