Ad

Using InnerHTML With React

- 1 answer

I've made a mini calculator using React.

It works, but I'm not sure I understand why. Could someone point me towards the concept that I'm not fully grasping here.

My code's below.

Here's what I expected: After the first operation (first time the getResult function is executed) I expected to have to write a conditional in the clearingState function to reset the innerHTML of <div id="display" to {this.state.string} as the getResult function sets it to the updateResult variable. Yet, it works without me having to do this adjustment. I don't understand why.

Thanks in advance..

<script type="text/babel">
  var Calculator = React.createClass({
      createString: function(event){
        var previousState = this.state.string;
        var target = event.target;
        var number = target.innerHTML;
        var newState = previousState+number;
        this.setState({string: newState});
      },
      clearingState: function(event){
        var newState = "";
        this.setState({string: newState});
      },
      getResult: function(){
        var stringResult = this.state.string;
        var updateResult = eval(stringResult);
        return document.getElementById("display").innerHTML = updateResult;
      },
      getInitialState: function(){
        return ({
          string: ""
        })
      },
      render: function(){
          return (
              <div>
                <div id ="display">{this.state.string}</div>
                <div id="main">
                    <div className="key zero" onClick={this.createString}>0</div>
                    <div className="key one" onClick={this.createString}>1</div>
                    <div className="key two" onClick={this.createString}>2</div>          
                    <div className="key three" onClick={this.createString}>3</div>
                    <div className="key four" onClick={this.createString}>4</div>
                    <div className="key five" onClick={this.createString}>5</div>
                    <div className="key six" onClick={this.createString}>6</div>
                    <div className="key seven" onClick={this.createString}>7</div>
                    <div className="key eight" onClick={this.createString}>8</div>
                    <div className="key nine" onClick={this.createString}>9</div>
                    <div className="key d" onClick={this.createString}>.</div>
                    <div className="key C" onClick={this.clearingState}>C</div>
                </div>
                <div id="operators">
                    <div className="key mp" onClick={this.createString}>*</div>
                    <div className="key dv" onClick={this.createString}>/</div>
                    <div className="key ad" onClick={this.createString}>+</div>
                    <div className="key sb" onClick={this.createString}>-</div>
                    <div className="key eq" onClick={this.getResult}>=</div>
                </div>
              </div>
          );
      }
  });

  ReactDOM.render(
    <Calculator/>,
    document.getElementById('calculator')
  )

Ad

Answer

Every time you change the state react calls the render function again, which means that if you wrote:

<div id ="display">{this.state.string}</div>

when you call clearingState function react will detect you changed the state and will render again your component and the statement {this.state.string} will be replaced for the new state value.

So, what is happening is: you are changing the state every time you call the createString function and then react calls the render function again to reflect the new state; then the user press the "=" operator and the getResult function is called and you manually changes the content of your display div; if the user press the "C" button the state is again updated and react calls render again to reflect the new state.

Another thing, is that you should not change the innerHTML property of your div manually. Instead, let react taking care of reflecting the state of your component. So, you should do this.setState({string: updatedResult}) and not worry about innerHTML.

Ad
source: stackoverflow.com
Ad