Больше 4х лет назад я влюбился в ReactJS и с тех пор все Front End приложения разрабатываю при помощи этого замечательного инструмента. За это время я и команды, в которых мне повезло поработать, наделали кучу ошибок, многие из которых были благополучно исправлены. Множество оптимальных решений было найдено в тяжелых и дорогостоящих экспериментах.

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

Как я работал над ReacjJS приложением

1. Stateful компоненты (классы) хуже hook-ов


Пожалуй, начать стоит с наиболее нашумевшей фичи ReactJS, которая появилась в версии 16.8+ Вопреки некоторым убеждениям, эта фича была выстрадана ошибками предыдущих поколений разработчиков и решает множество проблем. Если вы все еще используете компоненты-классы вместо хуков в 2019-ом, то вы совершаете большую ошибку и просто еще не поняли, в чем их преимущество. Я не буду в этой статье подробно это объяснять, посмотрите лучше это замечательное видео Дена Абрамова, но я просто не мог начать эту статью иначе

Это, конечно, не ошибка сама по себе, но подход классов по сравнению с хуками гораздо более подвержен ошибкам, о чем уже написано немало статей:

  1. Самые распространенные ошибки в вашем React коде, которые вы (возможно) делаете
  2. The 7 Most Common Mistakes that React Developers Make

2. Использование анонимных функций в качестве props


Если первая ошибка еще может быть воспринята, как дань моде, то знание второй, уверяю, спасет от бессонных ночей и головной боли. Ведь именно она заставялет приложение работать настолько неадекватно, что его пользователи могут навсегда разочароваться в ReactJS. А мы ведь хотим, чтоб пользователи его любили, так же, как и мы с вами, правда? Для избежания этой ошибки можно пользоваться очень простым правилом — никогда, НИКОГДА не передавать в качестве пропса компоненту анонимную функцию.

export default function MyOtherComponent() {
  return (
    <MyComponent getValue={i => i.value} /> {/* НИКОГДА не пишите так */}
  );
}

Более изощренный вариант этой ошибки может выглядеть как-то так (не читайте, если не знакомы с Redux):

import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import MyComponent from './MyComponent';
import { fetchProjectData, projectId } from "./store/projects"

const mapStateToProps = createStructuredSelector({
  projectId,
});

const mapDispatchToProps = {
  fetchProjectData,
};

const mergeProps = (
  { projectId, ...restState }: any,
  { fetchProjectData, ...restDispatch }: any,
  { memberId, ...restOwn }: any
) => ({
  ...restState,
  ...restDispatch,
  ...restOwn,
  fetchProjectData: () => fetchProjectData(projectId),
});

export default connect(
  mapStateToProps,
  mapDispatchToProps,
  mergeProps
)(MyComponent);

В обоих вариантах, в конечно итоге, в props компонента попадает анонимная функция. Это плохо потому, что при каждом рендере родительского элемента, эта фукнция будет ссылаться на новый объект в памяти, а, значит, не будет равна сама себе предыдущей, и ваш компонент благополучно будет перерендерен без надобности. Это так сильно может тормозить производительность вашего приложения, что вы сами начнете плеваться и разочаровываться в React, но все дело в АНОНИМНЫХ ФУНКЦИЯХ в props-ах. Просто не делайте так никогда — и будьте счастливы.

Проблема еще заключается в том, что, часто такая ошибка не делает ничего плохого. Код просто работает себе — и все. И ничего заметно плохого не происходит. Ровно до того момента, пока вы в очередной раз не запихнете туда анонимный вызов получения данных с сервера (второй пример) — тут то вы поймете всю серьезность проблемы. Накопление таких анонимных пропсов, в результате, замедлит ваше приложение до уровня опыта 1995 года, когда для загрузки страницы нам приходилось просить соседей освободить телефонную линию.

Еще пара слов, как же написать правильно. Вот как:

const getValue = i => i.value;

return default function MyOtherComponent() {
  return (
    <MyComponent getValue={getValue} />
  );
}

import { connect } from 'react-redux';
import { createStructuredSelector } from 'reselect';
import MyComponent from './MyComponent';
import { fetchProjectData, projectId } from "./store/projects"

const mapStateToProps = createStructuredSelector({
  projectId,
});

const mapDispatchToProps = {
  fetchProjectData,
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(MyComponent);

// и далее в компоненте
import React, { useEffect } from 'react';

export default function MyComponent({ fetchProjectData, projectId }) {
  useEffect(() => {
    fetchProjectData(projectId);
  }, [fetchProjectData, projectId]);

  return (
    <div>{/* Какой-то компонент здесь*/}</div>
  );
}

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

3. Несколько экземпляров React в приложении


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

Пожалуйста, не пытайтесь запихнуть на одну страницу больше одного экземпляра React приложения. На самом деле, в документации React нет запрета на такой подход, я даже встречал рекомендации поступать именно так в некоторых статьях (и, конечно же, сам делал в своих приложениях подобное), НО оптимизация такого подхода и согласование всех частей приложения, в этом случае начинает занимать больше половины всего рабочего времени. Этого легко можно избежать: например, если вам нужно реагировать на какие-то события в legacy коде в вашем новом React-приложении, — вы можете использовать событийную модель. Например вот так:

import React, { useCallback, useEffect } from 'react';
export default function MyComponent() {
  const reactHandlerOfLegacyEvent = useCallback((event) => {/* event handler */}, []);
  
  useEffect(() => {
    document.addEventListener("myLegacyEvent", reactHandlerOfLegacyEvent);
    return () => {
      document.removeEventListener("myLegacyEvent", reactHandlerOfLegacyEvent);
    };
  }, [reactHandlerOfLegacyEvent]);

  return ({/* здесь какой-то компонент */});
}

4. Написание собственных библиотек, вместо существующих с открытым исходным кодом


Эта проблема вообще не про ReactJS, а о всей разработке в целом. Конечно, пока вы только учитесь, написание большого количества собственных библиотек позволит вам быстрее развиваться и набивать шишки, но если вы хотите находиться на передовой кромке развития программирования, то просто обязаны хотя бы попробовать каждую из библиотек с открытым исходным кодом, которые решают ваши проблемы. Просто спрашивайте у поисковых роботов, не существует ли библиотек, которые решают вашу задачу, — они умеют отлично отвечать на подобные вопросы.

Я не будут приводить пример библиотек, которыми пользуюсь сам, т.к. знаю, что половина из них устареет уже через пару месяцев и на их место придут другие. И, казалось бы, это входит в противоречие с первоначальным утверждением. И правда, зачем использовать библиотеки, которые устареют через пару месяцев? Ответ очень прост — вы сможете увидеть решение тех проблем, которые перед вами еще не возникли. Вы сможете совершенствовать существующие наработки, или понять, как решить задачу гораздо лучше на примере проблем в существующих библиотеках. Это можно сделать, только взаимодействуя с миром разработки, посредством использования библиотек с открытым исходным кодом.

5. Боязнь использовать чужой код


Как и предыдущая ошибка, эта не присуща лишь ReactJS приложениям, но в них она встречается довольно часто. Как же часто я вижу, как великолепный джун смело рвется в бой и переписывает части кода, которые прекрасно работают и в которых нет проблем, только потому, что прочитали об одной из предыдущих 4х ошибок. Я и сам был таким. Да что там кривить душой, часто трачу время впустую и сейчас, просто потому что движение — это жизнь.

Но я так же научился понимать других разработчиков, их мысли и проблемы, с которыми они столкнулись. Видеть количество времени и сил, которые были потрачены (и не зря) на решение проблем. В 3х случаях из 5-ти, когда я берусь «улучшийть» чужой код — у меня в результате получается почти то же самое, что и было. Просто потому что на старте задачи ты, обычно, не видишь всех проблем, которые подстерегают тебя в будущем. Так что, сейчас я уважаю чужой код, каким бы странным и «устаревшим» он мне не казался. Что и вам советую.

Спасибо


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

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

Комментарии (43)


  1. RubaXa
    06.08.2019 14:13

    Написание собственных библиотек, вместо существующих с открытым исходным кодом

    Хмм и откуда по вашему взялись все эти библиотеки (тут список из вашего package.json), как и сам React?


    1. Free_ze
      06.08.2019 14:56

      вместо существующих

      Речь скорее про велосипеды.


      1. RubaXa
        06.08.2019 16:53
        +1

        Angular — велосипед
        Vue — велосипед рожденный под впечатлением от Angular
        React — велосипед, в его JSX это «огрызок» от E4X


        Весь OpenSource чей-то велосипед, которым кто-то поделился, либо из-за отсутствия (вероятность чего сейчас нулевая), либо из-за того, что он устал от текущих решений, которые за годы превратились в монстров и просто устарели технологически.


        1. Free_ze
          06.08.2019 17:47
          +1

          Не все «велосипед», что делается с нуля. Сейчас на рынке не найдется места второму React или Angular, которые не предложат чего-то большего (что делали они когда-то). Это и будет изобретением велосипеда. Цена должна быть адекватна профиту.


          1. RubaXa
            06.08.2019 18:06

            Нет «всё», вы просто не понимаете простую истину, если бы в своё время, эти инструменты не были вынесены на суд общественности как opensource, они никогда не смогли превратиться из обычного местечкового велосипеда в то чем они стали.


            1. Free_ze
              06.08.2019 18:42

              эти инструменты не были вынесены на суд общественности как opensource, они никогда не смогли превратиться

              «Суд общественности» рукоплескал еще одним яйцам в профиль или у нее были какие-то киллер-фичи, которые общественности полюбились?

              как opensource

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


              1. RubaXa
                06.08.2019 19:27

                «Суд общественности» рукоплескал еще одним яйцам в профиль или у нее были какие-то киллер-фичи, которые общественности полюбились?

                По началу, сообщество очень и очень холодно приняло тот же React или Angular 2. А если б в Vue был менее сырым и за ним стоял бы не никому неизвестный «чувак», а какая-нибудь крупная компания, то кто знает, какая бы расстановка сил была бы сейчас.


    1. Razzwan Автор
      06.08.2019 23:53

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


      1. RubaXa
        07.08.2019 07:39

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


        ps Сейчас, кстати, настало новое время, когда как раз хорошо не брать готовое, а создать новое, т.к. очень много новых технологий появилось, js больше не стоит на месте и развивается с каждым годом, поэтому можно делать велосипед с заделом на бедующее.


    1. smarthomeblog
      07.08.2019 12:49

      По всей видимости, речь идет о том, что если какая-то библиотека устраивает, но не нужно писать свою — достаточно использовать существующую. А вот если нет, то либо форк, либо свое.


  1. mayorovp
    06.08.2019 14:46

    Пожалуйста, не пытайтесь запихнуть на одну страницу больше одного экземпляра React приложения. [...] оптимизация такого подхода и согласование всех частей приложения, в этом случае начинает занимать больше половины всего рабочего времени

    А что именно тут надо оптимизировать и согласовывать?


    В моём представлении, несколько экземпляров React на странице возникают в ситуации, когда нужно разместить React-компонент на странице, построенной по другой технологии (angular, vue или даже jquery). Разумеется, в таком случае согласование компонентов отдаётся на откуп этой самой другой технологии — и не может быть проще чем согласование двух обычных компонентов на этой технологии. Но и сложнее оно не становится просто из-за того, что React-компонентов на странице стало аж два!


    1. Razzwan Автор
      07.08.2019 00:00

      Речь о том, что в подавляющем большинстве случаев две React точки входа в приложении можно заменить одной. По моему, сугубо субъективному мнению, именно так и нужно поступать. Согласование двух React точек входа сложнее потому, что нужно согласовывать:
      1. Обе React точки входа между собой
      2. Первую  React точку входа с приложением
      3. Вторую React точку вохода с приложением

      Для каждой из этих 3х задач придется писать свои велосипеды.

      Если оставить всего одну точку входа React в проложении, то согласовывать нужно будет только одну эту точку с приложением — и все. Причем это решение будет очень близким к конкретному куску документации React.

      Я трижды решал эту задачу разными способами. Лучшее решение (последнее) — это одна точка входа.


      1. mayorovp
        07.08.2019 05:47

        Как вы собрались заменять две точки одной, если первая из точек входа — "шапка" страницы, а вторая — контрол выбора даты на форме фильтрации?


        1. alsii
          07.08.2019 08:23

          1. mayorovp
            07.08.2019 08:35

            Ну хорошо, но у вас контрол выбора даты будет частью шапки сайта — или шапка сайта будет частью контрола выбора даты?


            Как по мне, так в любом случае какая-то чушь получается.


            1. alsii
              07.08.2019 11:13

              Нет. Будет пустой documentElement, который будет корневым элементом react и в котором будет два портала на контрол выбора даты и на шапку сайта.


              1. mayorovp
                07.08.2019 11:22

                И для того, чтобы достать дату из контрола, нужно будет обращаться к этому самому элементу? А если контролов выбора даты — несколько экземпляров — то ещё и уникальные идентификаторы для каждого надо выдумывать?


                1. alsii
                  07.08.2019 11:49

                  Вот тут и начинается то самое "согласование всех частей приложения" :(


                  А если контролов выбора даты — несколько экземпляров — то ещё и уникальные идентификаторы для каждого надо выдумывать?

                  Придется. Как и в случае с несколькими экземплярами react. Root-элемент в ReactDOM.render() вам все равно придется как-то передавать.


                  Ну и вообще, желание "достать данные из компонента", как то противоречит реактивной модели разработки с Unidirectional Data Flow. В той схеме, которую я предлагаю у вас будет один "react state", который будет отдаваться в общий state всего приложения.


                  1. mayorovp
                    07.08.2019 13:09

                    Вот тут и начинается то самое "согласование всех частей приложения"...

                    … которое ваши порталы лишь усложняют.


                    Ну и вообще, желание "достать данные из компонента", как то противоречит реактивной модели разработки с Unidirectional Data Flow.

                    А где вы в моём комментарии вычитали что-то про Unidirectional Data Flow и общий state всего приложения?


                    В ситуации, когда вы вынуждены размещать React-компоненты на "чужеродной" странице, у вас вообще в принципе не может быть никакого глобального состояния React-части приложения. Компоненты должны быть изолированы друг от друга и точка. Можно их даже в web component упаковать для большей красоты.



        1. Razzwan Автор
          08.08.2019 00:22
          -1

          Да, верно, с испльзованием порталов

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


          1. mayorovp
            08.08.2019 05:34

            Зачем шапке страницы и контролу выбора даты общее глобальное состояние?


  1. staticlab
    06.08.2019 15:05
    +2

    По опыту использования сторонних react-компонентов, очень часто они тащат гору зависимостей, которая весит даже больше самого компонента. Например, любят тащить recompose ради нескольких небольших функций. Только проблема в том, что recompose не поддаётся оптимизации и попадает в бандл весь целиком.


    С хуками проблема в том, что они прикручены сбоку и неявно зависят от контекста вызова. В случае класса всё-таки очевиднее, что он хранит в себе состояние.


    1. Razzwan Автор
      08.08.2019 00:26

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


  1. rboots
    06.08.2019 16:34

    Stateful компоненты (классы) хуже hook-ов

    Уже какой-то фашизм от функциональщиков. Вы пробовали создать действительно сложные приложения stateless-компонентами? Я пробовал, на нескольких проектах, с коллегами очень высокого уровня (Яндекс, UBS), потом тоже самое переписывали на ООП с уменьшением сложности приложения раза в три. Фронтенд должен быть statefull, в этом как бы идея Rich Internet Applications. Чтобы поддерживать фрактальную природу программы во фронтенд компоненты обязаны иметь состояние и инкапсулировать сложную логику внутри, не пуская вне, иначе или будет коллапс сложности или функционал будет бедным, возникнут проблемы с массштадированием приложения вглубь. Facebook делает социальную сеть, у них хорошие психологи, маркетологи, но у них нет хороших фронтенд-специалистов. Хватит за ними их бред повторять.


    1. Razzwan Автор
      07.08.2019 00:07

      Да, интересные мысли. Тоже об этом задумывался. Но тогда Angular и Vue выполняют похожие задачи.

      Я в последнем приложении (оно вполне себе большое) начал повсеместно использовать hooks, — и это моей команде дало возможность проще переиспользовать повторяющиеся куски кода (ранее для этих целей мы использовали HOC, что было гораздо менее наглядно и понятно). Покрывать тестами hooks, проще чем HOC-и. Опять же, все это субъективно.

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


      1. rboots
        07.08.2019 16:39

        Angular первой версии имел проблемы со слишком слабой инкапсуляцией, поэтому большие приложения на нём было сложно разрабатывать, но простые делались на ура. Не скажу за более новые версии, не работал, но уверен Google знает что делает. Vue это просто песня, сочитает простоту первого Angular и стабильность React. Его часто позиционируют как фреймворк для стартапов, но мы использовали его в энтерпрайз и тоже очень довольны. По субъективным ощущениям разработка идёт раза в два быстрее, чем на React, код более декларативный, поддержка проще, вид и логика разделены by design, много приятного синтаксического сахара. Если бы не повальный пиар React и распространённость в компаниях — я бы только на Vue и программировал.


        1. Razzwan Автор
          08.08.2019 00:30

          По сравнению с React Vue все еще слабоват. Те задачи, которые давно решены для React и Angular, все еще открыты для Vue. Наличие разных вариантов возможности разработки на Vue заставляет тратить время на выбор вариантов. В этом плане круче всех Angular. React что-то среднее в этом плане


          1. rboots
            08.08.2019 17:23

            Разные варианты это же замечательно. Вы можете писать в html-стиле или jsx-стиле. Можете использовать data или vuex. Выбор решения зависит от задачи. Гораздо хуже, когда создатели инструмента думают, что лучше вас знают вашу задачу и потребности и пытаются пропихнуть одно решение для всех случаев.
            Буквально сегодня пытался отключить a11y lint в react-script 3.0, так как у нас внутренний проект и accessability только съедает время. Вы знаете, что в react-script это невозможно? Точнее вы можете отключить проверку, но сам пакет всё равно будет устанавливаться, причём дважды, и выбрасывать ошибку при билде, если этот неиспользуемый пакет отсутствует. Во Vue даже близко таких проблем нет. Я бы поспорил какой проект более слабоват. React даёт прямой путь для новичков, но как только вы пытаетесь его хоть немного кастомизировать — вас ждут преключения. Я считаю, что это нормальный подход для пользовательского продукта, которым пользуются бабушки, но недупустимо для профессионального.


            1. Razzwan Автор
              08.08.2019 22:52

              Да, согласен. Пожалуй, react-scripts — это самое слабое место ReactJS. Я до сих пор не понимаю, как можно тащить столь отвратительный код такое долгое время. Полно есть альтернативных вариантов с нормальной архитектурой. Надеюсь, что это исправят в скором времени. Я и сам готов заняться этой задачей, если буду уверен, что обновление примут…

              Однако, что касается самих решений, тут React чуточку впереди. Библиотек больше и среднее качество их лучше. По крайней мере для тех задач, с которыми я успе столкнуться на обоих фреймворках


    1. Finesse
      07.08.2019 08:02
      +1

      Хуки != отсутствие состояния. Хуки это другой API для хранения состояния компонентов. Моя практика показала, что в подавляющем большинстве случаев компоненты на хуках не сложнее классовых компонентов и хуки позволяют намного красивее декомпозировать и переиспользовать код компонентов.


    1. Ungla
      07.08.2019 16:46

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


  1. Frimko
    06.08.2019 16:42
    +2

    Написание собственных библиотек, вместо существующих с открытым исходным кодом

    лучше заменить на — «Лень поиска уже готовых решений, взамен проработки своих велосипедов», да и что таить, порой эти «готовые решения с открытым исходным кодом» настолько ужасны, что проще свое написать(можно заметить как особо ленивые авторы тупо делают PR в свою репу, особо не заморачиваясь, что там внутри, главное решает проблему).


    1. Razzwan Автор
      07.08.2019 00:09

      Да, эдакая странная лень, которая силы не экономит, а наоборот, расходует впустую. Много таких. Я и сам таким бываю… Особенно, когда устал думать )


    1. smarthomeblog
      07.08.2019 12:55

      Кроме красоты кода открытых решений, нужно смотреть сколько народа их используют. Чем больше, тем, понятное дело, лучше. Так как баги, которые в своей либе еще зреют, они уже нашли и пофиксили. Был подобный опыт, когда товарищ не захотел использовать стандартную библиотеку для работы с датами и гордо написал свою — а про 29 февраля не подумал. Ну и сделал банальный день веселым :)


  1. JPEG
    06.08.2019 22:55
    +2

    Ну, куда это годится? Топ 5 ошибок = 1 очевидная ошибка + 1 холиворный топик + 3 ни разу не ошибки.


    А как же сломанный асинхронный setState? А бесконечный ре-рендер из-за сайд эффектов в функции рендеринга? А разные версии реакта из-за ошибок бандлинга? Забыли про key=i в map()? А то, что функциональные компоненты ни разу не PureComponet? Куча же всякой неочевидной фигни в реакте (я люблю реакт не меньше вашего)!


    1. Razzwan Автор
      07.08.2019 00:13

      Старался написать что-то новое, но, скорее, склонен с вами согласиться, чем оспаривать очень близкие к истине вещи. Хоть я и искренне считаю hooks лучше компонентов-классов.


  1. Finesse
    07.08.2019 07:48
    +1

    2 Использование анонимных функций в качестве props

    В этом пункте не хватает маленькой и очень важной детали: этот совет имеет смысл только если компонент, в который передаётся функция, мемоизирован (например, с помощью React.PureComponent или React.memo). Иначе рендер будет производиться в любом случае и описанный финт не поможет.


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


    1. Razzwan Автор
      08.08.2019 00:33

      Спасибо. Проверю и поправлю статью, если все, что написано подтвердится на практике


  1. faiwer
    07.08.2019 19:19

    С приходом хуков жизнь стала веселее, но сложнее. Каждый раз решая очередную неочевидную задачу я сталкиваюсь с головоломкой. Как бы мне эдак накрутить useEfect-ов, useRef-ов и useState-ов, чтобы они решали оптимально поставленную перед ними задачу. Чтобы нигде не "поехали" замыкания, чтобы непропустить какой-нибудь dependency и не создать этим страшно неочевидный и сложноотлавливаемый баг. Чтобы обезопасить себя от setState-ов после unmount-инга компонента. Чтобы не поломать ссылочную целостность и не потерять доступ к свежей версии переменных в замыкании. Это всё страшно интересно, но совсем непросто. Пока были pureComponent классы многие вещи реализовывались тривиально. А теперь это головоломки. Мне нравится.


    Но… почему многие говорят что hook-и проще? :) Вот попробуйте на досуге решить хотя бы простую задачу: написать хук useIsUnmount, который позволит вам узнать отмонтирован компонент или ещё нет. Решается в 5-8 строк… но требует нестандартного подхода (useRef).


    Ну или например решили вы создать очередной eventHandler и задействовали useCallback, задали ему правильных dependencies. Всё работает. Но если ваши dependencies меняются слишком часто — вы слишком часто пересоздаёте eventHandler и пере-render-ите древо ниже по курсу. А нужно ли это вам? Ведь eventHandler-ы для event-ов, а не для render-а. Ок, можно снова взять useRef. А нужно ли? Тут уже можно устроить холивар.


    Итак во всём. Есть задача — начинаешь думать и видишь много путей решения. Какой правильный? Какой hook-way лучше, какой хуже? Нам дали довольно низкоуровневые инструменты построения реактивности, и теперь мы с ними можем столько говнокода нагородить, который будет стрелять в самые неочевидные моменты жизненного цикла приложения… Могу привести пример.


    1. Razzwan Автор
      08.08.2019 00:36

      Вы пишите о разных вариантах решения задач. Вы знаете ответы. У вас их много. Не знаю, как у вас, у меня с компонентами-классами не всегда хотя бы одно решение находилось, а с хуками их много, — это ли не прекрасно?

      У меня линтер отлавливает неверные зависимости.

      Все проблемы, о которых вы пишите были и раньше, просто вы их не замечали под капотом. Он просто ждали своей очереди…


      1. faiwer
        08.08.2019 01:12

        Вы пишите о разных вариантах решения задач. Вы знаете ответы. У вас их много

        Ну я и пишу, что мне нравится этот подход. Головоломки это интересно. Но ведь есть бизнес, у него свои цели. Есть junior-ы и middle-ы. Вот как им писать код на хуках? Они вынужденно соберут все грабли какие только можно. Я пишу с использованием хуков с декабря, и кажется только щас начал постигать какой-то вменяемый путь. Натуральное жонглирование разными абстракциями.


        Все проблемы, о которых вы пишите были и раньше, просто вы их не замечали под капотом

        Да то разве проблемы. Потеря this, разбросанная по коду класса логика (т.к. нет миксинов), всякие мемоизаторы\селекторы\линзы и с хуками есть. Не знаю даже. С классами было может и неудобно, но довольно просто. Разрулить потерявшийся this и разрулить поехавшее замыкание это задачи разного порядка.


        У меня линтер отлавливает неверные зависимости.

        Только простые случаи могут хоть как-то быть отловленными линтером. В этом случае вы можете его просто вообще заменить на useAutoCallback и вообще забыть...


        1. Razzwan Автор
          08.08.2019 01:21
          -1

          Меня немного подергивать начинает, когда начинают писать про некий абстрактный «бизнес», который почему-то должен решать. Бред это. Не должен. Бизнес для людей. Интерес к разработке, — тоже для людей. Если разработчику не нравится его работа — он не сможет сделать ее хорошо. Так что, бизнес что угодно может решать, если разработчикам будет неинтересно работать с технологиями, которые продиктует бизнес — загнется такой бизнес.