Как использовать getDerivedStateFromProps в React 16.3 (ру субтитры)

https://www.youtube.com/watch?v=p_m4TrYGtCo
  • Перевод

Вышел перевод нового видео от команды hackage.tv, в котором очень доступно рассказано об использовании методов жизненного цикла в React 16.3 и getDerivedStateFromProps в частности.


Поделиться публикацией
Похожие публикации
Ой, у вас баннер убежал!

Ну. И что?
Реклама
Комментарии 12
  • 0

    Стенограммы нет?

    • 0
      Увы. Можете помочь, обновлю публикацию.
      p.s. большую часть видео идет речь только про getDerivedStateFromProps. Само видео короткое (9 мин)
    • +1

      То есть эти гении не додумались передавать prevProps (nullable) в этот метод и поэтому нужно дублировать prop в state? Ещё и не рассказано в какой момент вызывается этот метод.

      • 0

        Если ваш вопрос не троллинг, то вы можете найти ответ на него в этой ветке обсуждения на github:
        https://github.com/reactjs/rfcs/pull/6#discussion_r162865372


        Когда вызывается метод, можно увидеть на этой диаграмме:
        https://mobile.twitter.com/dan_abramov/status/981712092611989509

        • 0

          Не совсем понятно почему мы в том методе изолированы от prevProps и вынуждены прибегать к такому грязному костылю с дубляжом полей (да ещё и насильно делая компонент statefull "просто так"). Там случаем нигде не проскальзывало внятное объяснение причин?


          Честно говоря у меня много вопросов к 16.1+. Скажем я так и не понял как получить доступ к context полю в рядовых методах компонента (а не только в render). Ничего умнее:


          render()
          {
            return <Consumer>{some =>
            {
              this.someFromContext = some; // <= dirty trick
              return /* any jsx */;
            }</Consumer/>;
          }

          Случаем нигде не проскакивал reactWay по такому случаю?

          • 0
            function as a child — довольно распространенный подход (react-router, react-motion и т.д.), а сам Consumer предполагается использовать как-то так:
            <Consumer>
              {
                data => (
                  <MyComponent data={data} />
                )
              }
            </Consumer>
            

            Ну а дальше этот подход легко трансформировать в HOC.
            Получается, что компонент, использующий контекст, про сам контекст ничего не знает и работает с props привычным образом.
            • 0

              HOC это дополнительный уровень иерархии и это не бесплатно. <Consumer/> уже сам по себе создаёт 1 уровень (React Dev Tools его видит). С HOC их будет уже два. Открыл я свой проект и ужаснулся. На несколько DIV-ов гора обёрток над обёртками над обёртками. Впору уже делать доп. поле (помимо displayName), чтобы можно было скрывать всю эту шелуху.


              function as a child — довольно распространенный подход

              Ну и что? Это же просто неудобно для statefull компонент.

              • +1
                Вы хотели react way, я вам его дал. И делать именно так гораздо лучше, чем использовать этот костыль с «this.someFromContext = some».
                HOC это дополнительный уровень иерархии и это не бесплатно
                Любая строчка кода — это не бесплатно. Конкретно в нашем случае цена стремиться к нулю и я не представляю, какая должна быть вложенность (тысячи HOC?), что бы заметить хоть какое-то влияние на производительность. И уж точно это никогда не станет bottleneck, потому что он всегда будет в работе с DOM.
                На несколько DIV-ов гора обёрток над обёртками над обёртками
                Тут скорее проблема в средствах отладки, которые не позволяют все это дело отобразить в удобном виде, а не в самом подходе. Вы же понимаете, что если бы не было оберток, то был бы один раздутый компонент. Как мне кажется, это гораздо хуже.
                Это же просто неудобно для statefull компонент
                Можете привести пример, где это неудобно? За все время использования React не сталкивался с какими-то неудобствами этого подхода, даже наоборот.
                • 0
                  потому что он всегда будет в работе с DOM

                  Это не правда. DOM далеко не всегда является главным тормозом. Неудачная архитектура и бездумное использование фреймворка может заткнуть за пояс тормоза DOM-а. Я регулярно с этим сталкиваюсь в различных сторонних SPA. Минимальные изменения DOM заставляют куллер на CPU гудеть а мозг ждать.


                  В случае React для этого надо заставить постоянно рендерить большие куски древа, которые по факту почти не изменяются, и тем самым постоянно их реконсилировать. Это весьма не дёшево. Да и просто большого количества мелких компонент (списки, деревья и пр.), каждый из которых обёрнут натрое HOC-ми легко просадят вам производительность. А если память подождёт и сборщик мусора начнёт активно тупить, то мы получим стандартные дикие тормоза от внезапно повисшего SPA.


                  В случае Redux достаточно наплодить subscribe-ов (например квадратично — ячейки таблицы). И тогда CPU только и будет делать, что считать mapStateToProps и mapDispathToProps. А если их ещё и не мемоизировать, то оно умрёт в адских корчах ещё при рождении.


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

                  Вместо кучи обёрток был бы 1 быстро и эффективно работающий компонент. По правде говоря, на мой вкус, такие вещи вообще должны быть зарыты внутри самого React, где можно избежать массы бесполезных стадий. И вот это было бы гораздо лучше.


                  Если мы говорим о большом react+redux приложении со сложной историей, большой произвольной вложенностью, изобилием DOM, то при небольших ошибках с его архитектурой мы легко получаем весьма посредственную производительность. И если начать копать, то получается, что браузер только и делает, что тасует всякие { ...this.props, ...some.mix }. А потом сравнивает горы VDom между собой.

                  • 0
                    Можете привести пример, где это неудобно?

                    Код
                    // before
                    
                    handle = () =>
                    {
                        const { i18n } = this.context;
                        if(confirm(i18n('Are you sure?')))
                            this.props.remove();
                    }
                    
                    render()
                    {
                        return <some onClick={this.handle}>del</some>;
                    }
                    
                    // after
                    
                    render()
                    {
                        return <Consumer>i18n =>
                        {
                            this.i18n = i18n;
                            <some onClick={this.handle}>del</some>
                        }</Consumer>
                    }
                    
                    // or 
                    
                    I18nHoC(Component)
              • +1
                Не совсем понятно почему мы в том методе изолированы от prevProps и вынуждены прибегать к такому грязному костылю с дубляжом полей Там случаем нигде не проскальзывало внятное объяснение причин?

                Если у вас не получилось перейти по ссылке и почитать, то вот вам скриншоты оттуда


                Раз


                Два


                Особенно обратите внимание на листинг на втором скриншоте. Из-за того, что при первом render prevProps будут null, придется писать дополнительные условия. Без использования prevProps код выглядит чище, так что это еще вопрос, может быть именно внедрение prevProps было бы костылём.

                • 0
                  Если у вас не получилось перейти по ссылке и почитать, то вот вам скриншоты оттуда

                  Вы знаете, у меня и сейчас не получается. Может ссылка кривая. Даже поиск по странице по словам из скриншотов ничего не находит. Впрочем не важно, спасибо за скриншоты. Ребята предлагают костыль с setState во избежание проверки на null (TypeScript и все дела). Возможно это и правда имеет смысл. Лично я просто воткнул бы в качестве prevProps текущий props при инициализации и описал бы это в документации. Это тоже своего рода костыль. Но на мой вкус куда менее убогий текущего решения.

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

          Самое читаемое