Что такое условия Early Returns / Guard, почему вы должны их использовать и примеры того, как использовать в React

Повестка дня

В этой статье мы рассмотрим следующие разделы:

  • Основная концепция раннего возвращения
  • Причины использования раннего возврата
  • Использование раннего возврата с React
  • Использование раннего возврата с крючками

А теперь приступим.

Что такое ранний возврат?

Ранний возврат - это шаблон, который предлагает нам избегать вложенных операторов if-else, проверяя предварительные условия и возвращая или выбрасывая как можно раньше. Обычно раннее возвращение также называется защитной оговоркой или шаблоном вышибалы.

Базовый выдуманный пример этого шаблона - это поворот кода ниже

… Примерно так:

Я хотел бы упомянуть, что Swift (современный язык, изданный Apple для разработки iOS / MacOS) даже делает guard как встроенную языковую функцию!

Причины использования раннего возврата

1. Это делает наш код читаемым и понятным.

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

2. Это снимает нагрузку с нашего разума при работе в сложных условиях.

Представьте (или вспомните) случай, когда у нас есть много вложенных if-else ветвей в функции, как часто мы будем теряться при написании логики?

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

Как мы используем Early Return в React?

В React Component - это граница для создания наших строительных блоков пользовательского интерфейса, и на этом уровне легко применить Early Return. Например, мы можем вернуть Spinner, когда данные загружаются, вернуть Alert, когда есть ошибка, вернуть несколько сообщений, когда данные пусты, и вернуть «настоящий» презентационный элемент, когда данные готовы.

А как насчет крючков?

MyComponent в приведенном выше коде является презентационным компонентом, и мы можем просто поместить useData крючок (у нас есть этот настраиваемый крючок где-то в кодовой базе), чтобы позволить компоненту загружать данные самостоятельно:

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

То есть, приведенный ниже код НЕ действителен, и React будет регистрировать ошибки и предупреждения для вас, потому что ловушка useData2 и ловушка React.useMemo не всегда вызываются - порядок вызова хуков меняется.

Вы можете получить такие ошибки и предупреждения, как: «React обнаружил изменение порядка хуков, вызываемых XXX» и «Обработано больше хуков, чем во время предыдущего рендеринга».

Немедленное решение - переместить нулевую проверку внутри хуков:

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

Поддерживаемый подход к решению этой проблемы - использовать нашего старого доброго друга - render props.

То есть мы могли бы написать компоненты для загрузки data1 и data2 соответственно. Эти компоненты ничего не отображают, когда данные не готовы, и они вызывают children функцию для визуализации фактического dom, когда данные подготовлены. Я называю эти компоненты DataGuard

Когда у нас есть эти DataGuard, мы можем составить их следующим образом:

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

Интересным наблюдением является то, что мы начинаем видеть пирамиду вложенных компонентов при использовании DataGuard компонентов. Я думаю, что это прекрасно, поскольку вложение компонентов в дерево - это именно то, как работает React - если мы просто спросим себя: как мы используем компонент? Ответом может быть просто «мы помещаем его в другой компонент». Это верно вплоть до корневого компонента - того, который передается в ReactDOM.render функции.

Спасибо за прочтение :)

Примечание от Plain English

Вы знали, что мы запустили канал на YouTube? Каждое видео, которое мы снимаем, будет направлено на то, чтобы научить вас чему-то новому. Проверьте нас, нажав здесь, и обязательно подпишитесь на канал 😎