Назад

componentWillReceiveProps умер! Да здравствует getDerivedStateFromProps!

Если вы вдруг не заметили, то componentWillReceiveProps умер. Точнее не совсем, но в React 17 точно умрет. Пока вы можете его использовать как и раньше, но разработчики пометили его как устаревший и вместо него рекомендуют использовать getDerivedStateFromProps. Почему же так и как с этим жить? Давайте вместе разберемся.

Для начала разберемся чем не угодил метод componentWillReceiveProps? Если верить информации в официальном блоге, то проблема в том, что люди часто использовали этот метод не по назначению, что приводило к проблемам. Именно из-за этого от него было решено отказаться. Каких-то конкретных примеров "неправильного использования" я не нашел, но недавно я слышал мнение о том, что сейчас команда React работает над, так называемым, асинхронным рендерингом. Так вот, проблема была в том, что слово will подталкивало людей к мысли, что подобные хуки идеальное место, чтобы сделать асинхронный запрос, хотя это не так. Проблему это, кстати, не решило, но что сделано, то сделано. Вот в этой ветке Дэм Абрамов дискутирует на эту тему (думаю не только в ней).

Как более безопасную альтернативу предлагается использовать методы componentDidUpdate и getDerivedStateFromProps. Если с первых все более-менее понятно, то второй, лично у меня, вызвал сперва некое недоумение.

Во-первых, в отличии от componentWillReceiveProps, этот метод вызывается как и при первоначальной отрисовке, так и при перерисовках. Но это не отменяет того, что вы все еще должны задавать изначальное состояние. В дополнение стоит сказать, что если родительский компонент вызывает перерисовку, то этот метод будет вызван даже если, фактически, свойства не изменились.

Во-вторых, это статический метод, который на вход получает новые свойства (nextProps) и предыдущее состояние (prevState). И если вам это ни о чем не говорит, то, проще говоря, ключевое слово this там не доступно. И вот тут, возможно, вы, как и я, начали паниковать. Как же я буду вызывать this.setState, если но недоступно? Для решения этой задачи вам нужно провернуть такой фокус. Если вы вернули null, то это значит, что состояние не обновилось, а если же вернули объект, то эффект такой же, как от вызова this.setState.

Сказать, что я в восторге от этих нововведений я не могу. Это полностью ломает те шаблоны, к которым я привык.  Если раньше вы могли сравнить this.props.somenthing и nextProps.something, то теперь нам предлагают ложить свои свойства, которые необходимы для вычисления состояния, в само состояние. Почему же тогда не передать prevProps как аргумент? Да потому, что при первоначальной отрисовке аргумент prevProps будет не определен и каждый раз придется проверять, что он определен, прежде чем оперировать с ним. Ниже приведены конкретные примеры.

// С использованием componentWillReceiveProps
class ExampleComponent extends React.Component {
  state = {
    isScrollingDown: false,
  };

  componentWillReceiveProps(nextProps) {
    if (this.props.currentRow !== nextProps.currentRow) {
      this.setState({
        isScrollingDown:
          nextProps.currentRow > this.props.currentRow,
      });
    }
  }
}

// С использованием getDerivedStateFromProps
class ExampleComponent extends React.Component {
  state = {
    isScrollingDown: false,
    lastRow: null,
  };

  static getDerivedStateFromProps(nextProps, prevState) {
    if (nextProps.currentRow !== prevState.lastRow) {
      return {
        isScrollingDown:
          nextProps.currentRow > prevState.lastRow,
        lastRow: nextProps.currentRow,
      };
    }

    // Если изменений нет
    return null;
  }
}

Стоит отметить, что если вы определите componentWillReceiveProps и getDerivedStateFromProps одновременно (в одном компоненте), то вызван будет только getDerivedStateFromProps.

Надеюсь я помог вам пролить свет на темные моменты нового API React. На моей памяти это одни из самых серьезных изменений за длительное время в React.

Возможно вам будет интересно:

Как повысить производительность React приложений

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

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

Рецепт: Webpack 4 + React + Babel 7 = ❤️

Сегодня я собрал волю в кулак и, все-таки, перешел в своем давнем React проекте с Webpack 2 на Webpack 4. Не скажу, что это было сложно, но потратить немного времени, все же, пришлось. Признаюсь честно, это был мой уже второй подход. Я пытался это сделать когда он только вышел, но тогда быстро все не взлетело и я решил отложить. Теперь, когда все грабли уже успешно пройдены, то я решил написать эту небольшую статью, чтобы, возможно, облегчить вам страдания.