改善糟糕的进度条性能

IT技术 reactjs performance progress-bar mobx
2021-05-25 04:33:35

我正在尝试使用 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 存储是瓶颈,我没有在其他组件中使用该存储值。

感谢您为我度过黄金时光。

1个回答

MobX 不太可能成为这里的瓶颈。更让人担心的是setStaterender方法中的使用这几乎总是一个坏主意,因为setState总是会导致另一个渲染。因此,您最终可能会以比实际意图更频繁的方式渲染,这肯定会影响性能。同样,您不想从内部更新您的 MobX 商店render,因为它很可能会触发另一个渲染。

相反,尝试将您的逻辑移至程序的其他部分,并使渲染更多地成为“事后考虑”:您正在做的其他所有事情的最终结果。

在没有真正理解你的目标的情况下,这里有一个简单的 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方法非常简单。这通常是一个好兆头!