azinit / learn-frontend

Study examples during learning and exploring last frontend tools, libs, solutions.
2 stars 0 forks source link

Explore: 5 типичных ошибок при создании React компонентов (с хуками) в 2020 году #264

Closed azinit closed 3 years ago

azinit commented 3 years ago

https://habr.com/ru/company/quarkly/blog/508910/

azinit commented 3 years ago

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

azinit commented 3 years ago

1. Использование useState, когда нет необходимости в повторном рендере

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

image

На первый взгляд, вы можете спросить: А в чем, собственно, проблема? Разве не для этого было создано это состояние? И будете правы: всё отлично сработает, и проблемы вряд ли возникнут. Однако в React’е каждое изменение состояния влияет на компонент и, скорее всего, на его дочерние компоненты, то есть заставляет их выполнить повторный рендеринг.

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

azinit commented 3 years ago

2. Использование router.push вместо ссылки

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

Не history.push('/next-page');

Хотя для большинства пользователей это вполне рабочее решение, есть одна большая проблема: она появляется, когда дело касается реализации веб-доступности. Кнопка вообще не будет помечена как ссылка на другую страницу, а это значит, что скринридер не сможет ее идентифицировать. Сможете ли вы открыть ее в новой вкладке или окне? Скорее всего, тоже нет.

azinit commented 3 years ago

3. Обработка действий с помощью useEffect

Самое простое решение — установить функцию onSuccess туда, где вызов будет успешным.

image

Есть два хука useEffect: первый обрабатывает запрос данных к API во время первоначального рендеринга, а второй вызывает функцию onSuccess. То есть, если в состоянии нет загрузки или ошибки, но есть данные, то этот вызов будет успешным. Логично звучит, да?

Конечно, это почти всегда будет срабатывать с первым вызовом. Но вы также потеряете прямую связь между действием и вызываемой функцией. И нет 100% гарантии, что это произойдет только в том случае, если действие fetch будет успешным. А это именно то, что мы, разработчики, так сильно не любим.

azinit commented 3 years ago

4. Компоненты с единой ответственностью

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

image

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

azinit commented 3 years ago

5. useEffect с единой ответственностью

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

image

Существует два варианта использования хука: «сбор данных» (data-fetching) и «отображение пути» (displaying breadcrumbs). Оба обновляются с помощью хука useEffect. Этот самый хук useEffect сработает, когда fetchData и updateBreadcrumbs функционируют или меняется location. Основная проблема в том, что теперь мы также вызываем функцию fetchData при изменении location. Это может стать побочным эффектом, о котором мы и не подумали.