Идеи в React: ответы на 3 фундаментальных вопроса


Оглавление

  • О чем этот пост? Чего вам следует ожидать и чего ожидаю я.
  • #Вопрос 1 Что означает «декларативность» React?
  • #Вопрос 2 JSX: что и зачем?
  • #Вопрос 3 Почему неизменяемость важна при работе с React?
  • Заключение
  • Ссылки

Об этом посте

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

Объясняя ответы на вопросы, о которых я говорил выше, мы стремимся дать вам представление о философии React и идеях, на которых она основана.

Базовое знакомство с React, JavaScript и/или программированием необходимо для того, чтобы понять, в каком контексте обсуждаются темы. Хотя обсуждаемые темы, а именно декларативное программирование, JSX и неизменяемость, не зависят от React и являются обычными для программирования.

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

Что означает «декларативность» React?

В общем смысле программирования, декларативное программирование относится к подходу, когда через код мы объявляем/описываем цель нашей программы, конечную цель, или, другими словами, мы говорим только ответ на вопрос: «Чего мы хотим достичь в конце?». В мире React этот вопрос звучит примерно так: «Как это должно выглядеть?».

Это можно понять в отличие от так называемого «императивного стиля программирования», когда мы описываем шаги для выполнения задачи.

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

Императивный способ

const showElement = ele => {
  if(!ele.classList.contains('show')){
    ele.classList.add('show')
  }
}

const ele = document.getElementById('dummyElement');
if(boolState) showElement(ele)
else hideElement(ele)
// both of the functions called above, 
// define the DOM mutations needed to be done
// in order to do what their name suggests
Вход в полноэкранный режим Выйти из полноэкранного режима

Декларативный способ

boolState ? <Element /> : null
Вход в полноэкранный режим Выход из полноэкранного режима

«Почему это здорово и нужно?» — спросите вы. Ну, при таком стиле программирования мы можем сосредоточиться на том, как должен выглядеть наш пользовательский интерфейс, что является основной целью при разработке фронтенда. Нам не нужно обременять себя манипуляциями и очисткой в DOM. React делает эту тяжелую работу за нас эффективным и надежным способом, возможно, даже лучше, чем если бы мы реализовали ее сами.

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

В двух словах, код в декларативном стиле говорит вам «это должно выглядеть так», в то время как код в императивном стиле говорит вам «вот что вы должны сделать». Поэтому при разработке на React, возможно, не стоит думать о том, как вы собираетесь сделать определенную вещь, а начать с конца и подумать о том, чего вы хотите достичь.

ПРИМЕЧАНИЕ: Чтобы ваш React-код соответствовал этой философии, пожалуйста, избегайте выполнения мутаций DOM напрямую, просто потому что вы можете. Это вредит цели React, помимо того, что отрывает или вмешивается в то, как React управляет пользовательским интерфейсом.

JSX: что и зачем?

JSX или JavaScript XML — это расширение синтаксиса JavaScript, созданное сотрудниками Facebook для упрощения работы разработчиков.
Это действительно мощный синтаксис, который облегчает задачу создания и манипулирования HTML и добавления его в DOM в React.

const element = <h1>Hello, world!</h1>
Вход в полноэкранный режим Выход из полноэкранного режима

Этот забавный синтаксис тегов не является ни строкой, ни HTML.

Мы передаем древовидные структуры, состоящие из HTML и/или элементов React, как обычные значения JS, а он создает из них элемент HTML и добавляет его в DOM. Каждый элемент HTML, записанный в JSX, разбирается или преобразуется в вызов React.createElement.
Позволяя нам писать HTML в React, мы можем использовать возможности, предоставляемые React, для создания динамических веб-приложений.

Хотя использование JSX не является обязательным требованием, он представляет собой важную часть экосистемы React. Его создатели называют его «языком шаблонов, который поставляется со всей мощью JS». Он позволяет нам описывать пользовательский интерфейс в HTML, что значительно упрощает разработку в React за счет сокращения синтаксических накладных расходов на этапе разработки.

Использование JSX означает, что вы будете создавать нечто, называемое React Component, в котором разметка и логика тесно связаны. Эти компоненты или блоки образуют свободно связанный способ разделения проблем в соответствии со способом React, вместо того, чтобы разделять разметку и логику на отдельные файлы, как во многих других библиотеках или фреймворках.

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

Бонус: JSX предотвращает атаки инъекции или XSS (межсайтовый скриптинг). Поэтому встраивание пользовательского ввода в JSX не вызывает опасений. Щелкните здесь, чтобы узнать, как это делается.

Почему неизменяемость важна при работе с React?

Я предполагаю, что вы знакомы с иммутабельностью в React, поскольку практически в каждом руководстве по React она упоминается, поэтому я пропущу ее вперед. Здесь, по ходу дела, вы узнаете, как переплетаются судьбы данных Immutability и React. Это небольшое пояснение поможет вам понять, почему.

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

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

«Мы должны вычислить разницу, верно?! Мы узнаем, что изменилось, и все готово!» — скажете вы.

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

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


«Верно?»

Не так быстро. Эти объектные типы данных являются изменяемыми, и их ссылка не меняется, если их значения изменяются, в отличие от примитивных типов. Проверьте это и это. В таком порядке, добавлю я.

«Что же нам теперь делать? Как нам найти решение нашей проблемы «что изменилось»?».

Давайте сделаем шаг назад. Если мы каким-то образом решили эту проблему, это означает, что следующим шагом для React будет просто перерисовать DOM, поскольку он должен знать, что что-то изменилось. Не означает ли это, что React может работать, даже если он знает, что что-то изменилось, а не знает, что именно?

«Хм, логично. Но мы не хотим вычислять разницу, а ссылка не меняется с мутацией, так как же React узнает, что данные изменились?».

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

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

Таким образом, React остается слепым к фактическим низкоуровневым изменениям, которые вы делаете, но беспокоится только о том, сделали вы изменения или нет.

Есть способы, например, метод жизненного цикла shouldComponentUpdate или использование второго аргумента React.memo HOC, чтобы включить или реализовать глубокую проверку равенства, которая используется явно, чтобы в основном улучшить производительность, когда мы точно знаем, что неглубокая проверка вызывает гораздо больше нежелательных рендеров.

Неизменяемость также может помочь сделать код более явным, когда происходят изменения данных.

const object = { 
  x: 2, 
  y: 4 
}
const changedObject = performSomething(object)
object.x
object.y
changedObject.x
changedObject.y
Вход в полноэкранный режим Выход из полноэкранного режима

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

Это также упрощает поиск старого состояния.

Как мы достигаем неизменяемости в коде React в целом?

Для объектов мы можем использовать Object.assign или более новый синтаксис Spread. Если значение, которое вы хотите изменить, является вложенным, вы должны «распространить» свой путь на его уровень. Для массивов нужно либо возвращать новый массив, либо найти методы, которые обновляют массивы неизменяемым способом, а не на месте.

Вот некоторые из этих методов:

  • Array.slice
  • массив.карта
  • массив.фильтр
  • Array.concat

Избегать: unshift, shift, pop, push, splice

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

Да, реализуя неизменяемость, мы постоянно создаем новые объекты и массивы.

Это само по себе влияет на производительность, но это также повышает производительность приложения. Нам нужно поэкспериментировать на более детальном уровне, чтобы выяснить, кто из них выигрывает, хотя это также зависит от того, как все построено.
Библиотеки вроде Immutable.js попытались приблизить эффективность работы с immutables к эффективности работы с mutables, так что это облегчение, если постоянное создание новых значений вызывает у вас стресс.

React также предоставляет инструменты для работы с неизменяемыми структурами данных и повышения производительности вашего приложения. Помощники неизменяемости и миксины (не рекомендуется использовать) — вот несколько примеров.

Минусы:

  • Добавляет зависимостей и, возможно, немного больше кода.
    Это увеличивает зависимость, поскольку родные идиомы (встроенные методы, которые мы перечислили выше), используемые для реализации неизменяемости, не очень производительны, и нам обычно нужны внешние пакеты для реализации этой концепции в полной мере.

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

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

Заключение

Надеюсь, вы узнали немного о React и его философии из этого поста. Изначально я думал осветить еще одну тему «Использование пользовательских хуков для исправления бурения прописей вместо использования Context API или библиотеки управления состоянием», но, возможно, позже.

Кроме того, на некоторые из этих вопросов я наткнулся в комментарии к статье, которую я читал, где парень описывал, что бы он спросил или хотел, чтобы его спросили на собеседовании по React. Мне самому стало интересно, и когда я закончил поиски ответов, я подумал, почему бы не сделать пост.

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

До следующего раза, ребята. До встречи!

Ссылки

https://reactjs.org/docs/introducing-jsx.html
https://www.freecodecamp.org/news/what-the-heck-is-jsx-and-why-you-should-use-it-to-build-your-react-apps-1195cbd9dbc6/
https://egghead.io/learn/react/beginners/wtf-is-jsx
https://danburzo.github.io/react-recipes/recipes/immutability.html
https://reactkungfu.com/2015/08/pros-and-cons-of-using-immutability-with-react-js/
https://github.com/kolodny/immutability-helper
https://www.dottedsquirrel.com/declartive-imperative/

Оцените статью
devanswers.ru
Добавить комментарий