using innerHTML with React

12,110

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.

Share:
12,110

Related videos on Youtube

Vera
Author by

Vera

Updated on June 04, 2022

Comments

  • Vera
    Vera almost 2 years

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

    • azium
      azium over 8 years
      Every time you call setState, React automatically calls render again (with the new state). Out of curiosity, are you using the React official docs as a guide?
    • azium
      azium over 8 years
      You should never need to manually update innerHTML in a React application. You should only call setState and let React handle updating the DOM for you.
    • Vera
      Vera over 8 years
      @azium, thank you for your explanation. I replaced this: return document.getElementById("display").innerHTML = updateResult; with this instead: this.setState({string: updateResult}); And you're right about setState and rendering. I still don't understand though, why that previous code worked.. as the way it was written before I really thought I was overriding the {this.state.string} with my updateResult variable. Sorry that I'm being slow to catch up on this... And yes, I am reading the docs, though not always understanding :)
  • Vera
    Vera over 8 years
    Thank you. I guess I wasn't getting it because I thought I was modifying what's in the render function with my call to getResult, which is a silly thought now that I think of it more. Thanks a lot to the both of you @azium as well :)