Улучшение плохой производительности индикатора выполнения - PullRequest
2 голосов
/ 02 июня 2019

Я пытаюсь передать состояние выполнения в другой индикатор выполнения с помощью хранилища 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 Ответ

1 голос
/ 03 июня 2019

MobX вряд ли будет узким местом здесь.Больше всего беспокоит использование setState в методе render.Это почти всегда плохая идея, потому что 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")
);

CodeSandbox

Как видите, метод render очень прост.Обычно это хороший знак!

...