В моей предыдущей статье я говорил о взломе цикла событий для повышения производительности вашего приложения. Ваша цель - поддерживать 60 FPS на всем протяжении. Все это применимо также к реагированию или реагированию на собственное приложение. Так что, если вы еще не читали, возможно, сейчас самое подходящее время для этого.

Вот несколько вещей, которые вы можете сделать, если используете React или React Native, чтобы поддерживать более высокий FPS.

1. Используйте PureComponent или shouldComponentUpdate.

PureComponent в react выполняет поверхностное сравнение свойств и состояния перед обновлением компонента. Он выполняет повторный рендеринг только при незначительном изменении свойств или состояния.
Метод жизненного цикла shouldComponentUpdate используется в обычном не чистом компоненте React для отмены повторного рендеринга путем возврата false в определенных сценариях.

Следующие два примера кода делают то же самое.

class MyComponent extends React.PureComponent {
  //
}
class MyComponent extends React.Component {
  //
  shouldComponentUpdate(nextProps, nextState) {
    if(this.props.firstProp === nextProps. firstProp &&
       this.props.secondProp === nextProps.secondProp) {
      return false;
    }
    return true
  }
  //
}

Оба приведенных выше примера могут помочь вам сэкономить зря рендеры. Первый пример уже реализует для вас логику shouldComponentUpdate. Второй пример дает вам немного больше контроля. Вы можете сохранить состояние в компоненте и остановить повторный рендеринг, если состояние не изменилось. Нравится

class MyComponent extends React.Component {
  shouldComponentUpdate(nextProps, nextState) {
    if(this.state.isLoading === nextState. isLoading) {
      return false;
    }
    return true
  }
}

2. Используйте ключевой атрибут в элементах списка.

Список - это наиболее часто используемая вещь в любом приложении. Если вы не укажете уникальный ключ для каждого элемента списка, response будет повторно отображать каждый элемент при добавлении или удалении любого элемента из списка. Имея уникальный ключ для каждого элемента списка, saves реагирует на повторную визуализацию снова.

class MyComponent extends React.PureComponent {
  render() {
    return this.props.data.map((item, i) => {
      return <Text key={item.id}>{item.title}</Text>
    });
  }
}

3. Связывайте на ранней стадии и не создавайте функций внутри рендера.

Сделай это

class MyComponent extends React.PureComponent {
  
  constructor(props) {
    super(props);
    this.doWork = this.doWork.bind(this);
  }
  doWork() {
    // doing some work here.
    // this.props.dispatch....
  }
  
  render() {
    return <Text onPress={this.doWork}>Do Some Work</Text>
  }
  
}

Не делайте этого внутри рендера.

<Text onPress={ () => this.doWork() }>Do Some Work</Text>

or

<Text onPress={ this.doWork.bind(this) }>Do Some Work</Text>

Поскольку рендеринг вызывается очень часто, и каждый раз, когда вы выполняете одно из двух вышеперечисленных действий, создается новая функция.
Если вы хотите передать аргументы функции doWork, вам может потребоваться создать дочерний компонент и передать функцию как опора.

<child arg1={arg1}></child>

И в дочернем компоненте.

doWork() {
  console.log(this.props.arg1);
}
render() {
  return <Text onPress={this.doWork}>Do Some Work</Text>
}

Если создание компонента является непосильной задачей, то всегда есть небольшой компромисс в производительности. Вы можете использовать закрытие, подобное следующему. Функция будет создаваться при каждом повторном рендеринге.

doWork = (param) => () => {
 console.log(param)
}
<Text onPress={this.doWork(someVarParam)}Do Some Work With Args</Text>

В таких случаях взвесьте свои требования к удобочитаемости и производительности.

4. Не обновляйте состояние и не отправляйте действия в componentWillUpdate.

Метод жизненного цикла componentWillUpdate используется для подготовки к обновлению, а не для запуска другого. Если вы хотите установить состояние, сделайте это в componentWillReceiveProps. И предпочитайте componentDidUpdate для отправки любых действий redux через componentWillReceiveProps.

5. Используйте VirtualizedList, FlatList и SectionList для больших наборов данных.

В соответствии с собственными документами React, VirtualizedList, FlatList и SectionList являются эффективным интерфейсом для отображения списков, поскольку они используют меньший объем памяти. Поэтому, если у вас есть список с сотнями строк, не все из них загружаются на экран, пока вы не прокрутите его вниз.
VirtualizedList является основой как для FlatList, так и для SectionList. А если у вас есть неизменяемый набор данных, вы должны использовать VirtualizedList напрямую.

6. Используйте Perf monitor, чтобы смотреть FPS.

Откройте инструменты разработчика и включите монитор производительности. Теперь, когда вы начинаете взаимодействовать, перемещаться или прокручивать приложение, вы можете иногда видеть падение FPS. И в основном это в потоке JS, а не в потоке собственного пользовательского интерфейса. Так что начните искать болевые точки, где падает FPS. Возможно, вы устанавливаете состояние или отправляете действия redux в неправильном месте. Или слишком много синхронной работы над потоком JS.

Я расскажу о более продвинутых техниках в моей следующей статье о React Native. Вы можете следить за мной, чтобы получать обновления, когда будут опубликованы новые истории :)
Если вы хотите что-то добавить, пожалуйста, оставьте это в разделе комментариев.