Reputation: 26565
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
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>
<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
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>
<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>
<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