I am trying to pass progress state to other progress bar by using the MobX store.
There are two progress bars. One of them should be changing independently in a short period(about 2secs). I used setTimeOut
to increase the current progress and it worked well. Then I tried to save the current progress value into the MobX store to pass to another component. After this, the performance of the progress bar was degraded.
render() {
...
if (tradingProgress.progress > 100) {
this.setState(prevState => ({
tradingProgress: {
...prevState.tradingProgress,
progress: 100,
},
}));
} else if (tradingProgress.isTrading) {
setTimeout(() => {
this.setState(prevState => ({
tradingProgress: {
...prevState.tradingProgress,
progress: prevState.tradingProgress.progress + 5,
},
}));
}, 100);
}
...
// save current progress to mobx store.
// convertProgress, setConvertProgress are in my mobx store.
if (tradingProgress.progress !== convertProgress && tradingProgress.isTrading) {
setConvertProgress(tradingProgress.progress); // in mobx store: this.convertProgress = currentProgress
}
I think using the MobX store frequently is the bottleneck, and I didn't use that store value in other components.
Thanks for spending your golden time for me.
MobX is unlikely to be the bottleneck here. What's more worrying is the use of setState
in the render
method. This is almost always a bad idea, because setState
always causes another render. So you could end up rendering way more often than you actually meant to, which can definitely impact performance. Likewise, you don't want to update your MobX store from inside render
, as it's very likely to trigger another render.
Instead, try to move your logic to other parts of the program, and have rendering be more of an 'afterthought': a final consequence of everything else you're doing.
Without really understanding your goal, here's a demonstration with a simple MobX store backing it.
import React from "react";
import ReactDOM from "react-dom";
import { action, decorate, observable } from "mobx";
import { inject, Provider, observer } from "mobx-react";
class UIStore {
convertProgress = 0;
setConvertProgress = progress => {
if (this.convertProgress < 100) {
this.convertProgress = progress;
}
};
}
decorate(UIStore, {
convertProgress: observable,
setConvertProgress: action
});
const store = new UIStore();
class TradingThing extends React.Component {
state = { progress: 0 };
componentDidMount() {
this.setState({ interval: setInterval(this.tick, 100) });
}
componentWillUnmount() {
clearInterval(this.state.interval);
}
tick = () => {
const { convertProgress, setConvertProgress } = this.props.store;
const { progress } = this.state;
setConvertProgress(convertProgress + 1);
if (progress < 100) {
this.setState({ progress: progress + 5 });
}
};
render() {
return (
<>
<div>Progress from component state: {this.state.progress}</div>
<div>Progress from MobX state: {this.props.store.convertProgress}</div>
</>
);
}
}
const TradingProgress = inject("store")(observer(TradingThing));
ReactDOM.render(
<Provider store={store}>
<TradingProgress />
</Provider>,
document.getElementById("root")
);
CodeSandbox
As you can see, the render
method is very simple. This is usually a good sign!