xRobot
xRobot

Reputation: 26565

How to avoid to use 2 state variable in my case?

I am looking for a way to optimize my code.

Is there a way to use only 1 state variable ( started ) instead of 2 ( started and now ) ?

This is my code ( a very simple timer ):

var Timer = React.createClass({
  getInitialState: function () {
    return {
      started: new Date().getTime(),
      now: 0
    }
  },
  render: function () {
    return (
      <div>
        <strong>{this.state.now}</strong>
        <button type="button" onClick={this.resetCounter}>Reset</button>
      </div>
    );
  },
  componentDidMount: function () {
    this.tickInterval = setInterval(this.doTick, 1000);
  },
  componentWillUnmount: function () {
    clearInterval(this.tickInterval);
  },
  doTick: function () {
    let newDate = new Date().getTime();
    let newCounter = Math.round((newDate - this.state.started) / 1000);
    this.setState({ now: newCounter });
  },
  resetCounter: function () {
    this.setState({ started: new Date().getTime(), now: 0 });
  },
});

ReactDOM.render(<Timer />, document.getElementById('root'));

Upvotes: 0

Views: 50

Answers (2)

DroidNoob
DroidNoob

Reputation: 1143

If you don't care about incrementing the state, this is the way to go

var Timer = React.createClass({

    getInitialState: function () {
        return {
            started: 0,
        }
    },


    render: function () {

        return (
            <div>
                <strong>{this.state.started}</strong>
                &nbsp;
                <button type="button" onClick={this.resetCounter}>Reset</button>
            </div>
        );
    },


    componentDidMount: function () {
        this.tickInterval = setInterval(this.doTick, 1000);
    },


    componentWillUnmount: function () {
        clearInterval(this.tickInterval);
    },

    doTick: function () {
        this.setState({ started:this.state.started+1});
    },
    resetCounter: function () {
        this.setState({ started:0});
    },

    });



    ReactDOM.render(<Timer />, document.getElementById('root'));

Check out the jsfiddle

Upvotes: 1

noveyak
noveyak

Reputation: 3300

Depending on how much you care about accuracy you can just store something like currentTicks and increment it by 1 in your doTick function. There is no guarantee that each interval is exactly a second though.

var Timer = React.createClass({


getInitialState: function () {
    return {
      tick: 0,
    }
},

render: function () {
    return (
        <div>
            <strong>{this.state.tick}</strong>
            &nbsp;
            <button type="button" onClick={this.resetCounter}>Reset</button>
        </div>
    );
},


componentDidMount: function () {
    this.tickInterval = setInterval(this.doTick, 1000);
},


componentWillUnmount: function () {
    clearInterval(this.tickInterval);
},

doTick: function () {
    this.setState({ tick: this.state.tick + 1 });
},
resetCounter: function () {
    this.setState({
      tick: 0
    });
},

});

ReactDOM.render(<Timer />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root">
<!-- my app renders here -->
</div>

Another way is use forceUpdate to force the component to rerender every second, but only store the start time. In general, I don't think this is great though and you would probably be better off doing what you are doing now. Here is an example if you are curious

var Timer = React.createClass({

componentWillMount() {
  this.forceUpdate = this.forceUpdate.bind(this);
},
  
getInitialState: function () {
    return {
      timeStarted: Date.now(),
    }
},

render: function () {
    return (
        <div>
            <strong>{Math.round((Date.now() - this.state.timeStarted) / 1000)}</strong>
            &nbsp;
            <button type="button" onClick={this.resetCounter}>Reset</button>
        </div>
    );
},


componentDidMount: function () {
    this.tickInterval = setInterval(this.forceUpdate, 1000);
},

componentWillUnmount: function () {
    clearInterval(this.tickInterval);
},

resetCounter: function () {
    this.setState({
      timeStarted: Date.now()
    });
},

});

ReactDOM.render(<Timer />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root">
<!-- my app renders here -->
</div>

Upvotes: 1

Related Questions