改善糟糕的进度条性能
Improve poor progress bar performance
我正在尝试使用 MobX 存储将进度状态传递给其他进度条。
有两个进度条。其中之一应该在短时间内(大约 2 秒)独立变化。我使用 setTimeOut
来增加当前进度并且效果很好。然后我尝试将当前进度值保存到 MobX 存储中以传递给另一个组件。在此之后,进度条的性能下降。
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
}
我认为频繁使用 MobX 存储是瓶颈,我没有在其他组件中使用该存储值。
谢谢你为我度过你的黄金时光
MobX 不太可能成为这里的瓶颈。更让人担心的是在render
方法中使用了setState
。这几乎总是一个坏主意,因为 setState
总是会导致另一个渲染。所以你最终可能会比你实际想要的更频繁地渲染,这肯定会影响性能。同样,您不想从 render
内部更新您的 MobX 存储,因为它很可能会触发另一个渲染。
相反,尝试将您的逻辑移动到程序的其他部分,并让渲染更像是一个 'afterthought':您正在做的所有其他事情的最终结果。
在没有真正理解您的目标的情况下,这里有一个简单的 MobX 存储支持它的演示。
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")
);
如您所见,render
方法非常简单。这通常是一个好兆头!
我正在尝试使用 MobX 存储将进度状态传递给其他进度条。
有两个进度条。其中之一应该在短时间内(大约 2 秒)独立变化。我使用 setTimeOut
来增加当前进度并且效果很好。然后我尝试将当前进度值保存到 MobX 存储中以传递给另一个组件。在此之后,进度条的性能下降。
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
}
我认为频繁使用 MobX 存储是瓶颈,我没有在其他组件中使用该存储值。
谢谢你为我度过你的黄金时光
MobX 不太可能成为这里的瓶颈。更让人担心的是在render
方法中使用了setState
。这几乎总是一个坏主意,因为 setState
总是会导致另一个渲染。所以你最终可能会比你实际想要的更频繁地渲染,这肯定会影响性能。同样,您不想从 render
内部更新您的 MobX 存储,因为它很可能会触发另一个渲染。
相反,尝试将您的逻辑移动到程序的其他部分,并让渲染更像是一个 'afterthought':您正在做的所有其他事情的最终结果。
在没有真正理解您的目标的情况下,这里有一个简单的 MobX 存储支持它的演示。
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")
);
如您所见,render
方法非常简单。这通常是一个好兆头!