Топ 5 ошибок в моих ReactJS приложениях

Больше 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-ти, когда я берусь «улучшийть» чужой код — у меня в результате получается почти то же самое, что и было. Просто потому что на старте задачи ты, обычно, не видишь всех проблем, которые подстерегают тебя в будущем. Так что, сейчас я уважаю чужой код, каким бы странным и «устаревшим» он мне не казался. Что и вам советую.

Спасибо


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

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

Комментарии 55

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

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

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

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

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


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

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

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

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

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

              как opensource

              Вопросы лицензии — это вообще ортогональное понятие. Есть море проприетарных решений, которые пользуются популярностью.
                –1
                «Суд общественности» рукоплескал еще одним яйцам в профиль или у нее были какие-то киллер-фичи, которые общественности полюбились?

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

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

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


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

          0
          По всей видимости, речь идет о том, что если какая-то библиотека устраивает, но не нужно писать свою — достаточно использовать существующую. А вот если нет, то либо форк, либо свое.
          +1
          Пожалуйста, не пытайтесь запихнуть на одну страницу больше одного экземпляра React приложения. [...] оптимизация такого подхода и согласование всех частей приложения, в этом случае начинает занимать больше половины всего рабочего времени

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


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

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

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

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

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

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

              • НЛО прилетело и опубликовало эту надпись здесь
                  0

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


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

                  • НЛО прилетело и опубликовало эту надпись здесь
                      0

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

                      • НЛО прилетело и опубликовало эту надпись здесь
                          0
                          Вот тут и начинается то самое "согласование всех частей приложения"...

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


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

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


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

                • НЛО прилетело и опубликовало эту надпись здесь
                    0
                    Да, верно, с испльзованием порталов

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

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

                +9

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


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

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

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

                  P.S.: И вообще не в их интересах, чтобы интернет рос, в их интересах, чтобы люди сидели не на разнообразных сайтах, а в facebook. Они создали Redux и сами не используют его. Они создали React с кучей архитектурных проблем и медленной разработкой и вложили кучу денег в пиар, хотя он не приносит им денег. Ничего не хочу сказать, просто странно, учитывая природу их основного бизнеса.
                    +1
                    Да, интересные мысли. Тоже об этом задумывался. Но тогда Angular и Vue выполняют похожие задачи.

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

                    По поводу заговора, тоже согласен. Он вполне может быть. Хотя я больше верю в благие намерения, не компаний, но разработчиков.
                      0
                      Angular первой версии имел проблемы со слишком слабой инкапсуляцией, поэтому большие приложения на нём было сложно разрабатывать, но простые делались на ура. Не скажу за более новые версии, не работал, но уверен Google знает что делает. Vue это просто песня, сочитает простоту первого Angular и стабильность React. Его часто позиционируют как фреймворк для стартапов, но мы использовали его в энтерпрайз и тоже очень довольны. По субъективным ощущениям разработка идёт раза в два быстрее, чем на React, код более декларативный, поддержка проще, вид и логика разделены by design, много приятного синтаксического сахара. Если бы не повальный пиар React и распространённость в компаниях — я бы только на Vue и программировал.
                        0
                        По сравнению с React Vue все еще слабоват. Те задачи, которые давно решены для React и Angular, все еще открыты для Vue. Наличие разных вариантов возможности разработки на Vue заставляет тратить время на выбор вариантов. В этом плане круче всех Angular. React что-то среднее в этом плане
                          0
                          Разные варианты это же замечательно. Вы можете писать в html-стиле или jsx-стиле. Можете использовать data или vuex. Выбор решения зависит от задачи. Гораздо хуже, когда создатели инструмента думают, что лучше вас знают вашу задачу и потребности и пытаются пропихнуть одно решение для всех случаев.
                          Буквально сегодня пытался отключить a11y lint в react-script 3.0, так как у нас внутренний проект и accessability только съедает время. Вы знаете, что в react-script это невозможно? Точнее вы можете отключить проверку, но сам пакет всё равно будет устанавливаться, причём дважды, и выбрасывать ошибку при билде, если этот неиспользуемый пакет отсутствует. Во Vue даже близко таких проблем нет. Я бы поспорил какой проект более слабоват. React даёт прямой путь для новичков, но как только вы пытаетесь его хоть немного кастомизировать — вас ждут преключения. Я считаю, что это нормальный подход для пользовательского продукта, которым пользуются бабушки, но недупустимо для профессионального.
                            0
                            Да, согласен. Пожалуй, react-scripts — это самое слабое место ReactJS. Я до сих пор не понимаю, как можно тащить столь отвратительный код такое долгое время. Полно есть альтернативных вариантов с нормальной архитектурой. Надеюсь, что это исправят в скором времени. Я и сам готов заняться этой задачей, если буду уверен, что обновление примут…

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

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

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

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

                          0
                          Да, эдакая странная лень, которая силы не экономит, а наоборот, расходует впустую. Много таких. Я и сам таким бываю… Особенно, когда устал думать )
                            0
                            Кроме красоты кода открытых решений, нужно смотреть сколько народа их используют. Чем больше, тем, понятное дело, лучше. Так как баги, которые в своей либе еще зреют, они уже нашли и пофиксили. Был подобный опыт, когда товарищ не захотел использовать стандартную библиотеку для работы с датами и гордо написал свою — а про 29 февраля не подумал. Ну и сделал банальный день веселым :)
                              0
                              извиняюсь, что так поздно. Но к примеру в моем случае, я пишу энтерпрайз. Пришел к выводу, что лучше работать как команда VK. Скачать либу к себе, разобрать и модифицировать под свои нужды. Дело в том, что приходится писать экзотические вещи, которых либо нет, либо они реализованы не так, как нужно тебе. А когда ты пишешь автору свой PR с новым функционалом, ему такое не нравится и подобное пропускают. Так возникают новые проекты и кол-во человек в открытых решениях, порой не имеет значение, они просто популярны, не более, код в них может быть такой-же отвратный и плохо кастомизируемый.
                            +4

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


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

                              0
                              Старался написать что-то новое, но, скорее, склонен с вами согласиться, чем оспаривать очень близкие к истине вещи. Хоть я и искренне считаю hooks лучше компонентов-классов.
                              +1
                              2 Использование анонимных функций в качестве props

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


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

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

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


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


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


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

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

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

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

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


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

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


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

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

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

                                  преждевременная оптимизация в полный рост.


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

                                  в случае если компонент не использует ни memo(), ни PureComponent, он все равно перерендерится, даже если все пропсы равны. В этом примере в консоли видно, что при измении текста компонент без memo все равно ре-рендерится, несмотря на то что count не меняется.


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

                                    +1
                                    Как и со всеми оптимизациями производительности, нужно замерять и искать узкие места, а не уповать на волшебные правила передачи функций.

                                    Ну это смотря как подходить к процессу создания приложения. Мне лично проще не создавать узких мест и везде использовать memo/selectors/dependencies-for-hook/etc. Это мало чем отличается от написания приложения в лоб. И да, просто анонимные функции при этом (обычно) — зло.


                                    К реальным оптимизациям (которые могут быть преждевременными) можно отнести вопросы архитектуры, какие-нибудь кастомные хуки для redux-а (к примеру древовидный connect), сложные древа селекторов, линзы, трансдьюсеры и прочие хитрости. А обыкновенные memo сложно назвать преждевременной оптимизацией.


                                    ИМХО.

                                      +1

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

                                        0

                                        Качество материалов по React обычно очень низкое. Полностью поддерживаю. Причём как у нас, так и в английском интернете. Что не статья, то epic fail.

                                          0
                                          В чем проблема? Напишите материал высокого качества. С удовольствием почитаю. По поводу memo — спасибо за дополнение.
                                            0

                                            Думаю лучше всего начать с документации. Первым же делом года 3 назад я просто прочёл от корки до корки всю документацию React, Redux, а чуть позже Reselect. Это сняло 95% вопросов и очень сильно упростило жизнь. Почти все ошибки и непонимание React кроется в том, что народ учится по простым статьям не вдаваясь в детали того, как и почему оно там работает.


                                            Если вы в какой-то момент поставите перед собой вопрос: "а могу ли я за неделю сам написать свой упрощённый react", и ответите на него утвердительно, значит вы прочитали документацию внимательно :)

                                          0
                                          Не того поблагодарил за memo. Спасибо
                                        0
                                        Пробую создать локально такой же пример — у меня нет разницы между memo и не memo… Возможно, я что-то неверно понимаю. Можете скинуть информацию на более развернутое объяснение, как это должно работать?
                                          +2
                                          kentcdodds.com/blog/usememo-and-usecallback
                                          ближе к концу статьи
                                            0

                                            Вся информация есть в документации. Я решительно не понимаю почему её никто не читает...


                                            Суть простая: все компоненты по-умолчанию всегда рендерятся со всеми подкомпонентами. Всё древо целиком. Не важно при этом одинаковые props вы передаёте или всё время разные. react ничего не проверяет и рендерит vdom-tree целиком. Всё поддрево. И для того чтобы этого избежать — необходимо давать react-у понять когда этого можно избежать. Все ссылки выше об этом. Но это только самая вершина айсберга. Настоящие immutable SPA пишутся куда более замороченно, чем просто понатыкать везде мемошек )

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

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