Дэн Щербаков ⚛️
96 subscribers
20 photos
49 links
Канал для фронтенд-разработчиков о том, как развиваться и увеличивать зарплату.

Senior Frontend Developer с 6 годами опыта. За этот период увеличил зарплату почти в 7 раз.

Начинайте тут: https://yangx.top/code_lab/280
加入频道
Полезные практики в React:

- Сократить код обращения к this.state можно, пользуясь деструктуризацией:

const { firstState, secondState } = this.state

- Вынести за пределы компонента логику коллебка можно, используя функцию высшего порядка:

const handler = itemToFind => item => item.title.includes(itemTiFind)

Здесь функция handler возвращает функцию, которая передается, например, в map и используется для фильтрации.

#React #JS
Работа браузера: рендеринг в деталях

Как процесс, рендеринг выглядит так:

1. Браузер формирует из HTML DOM-дерево...
2. Затем обрабатывает CSS и создает CSSOM.
3. На их основе создается Rendering Tree.
4. Вычисляется положение элементов на странице.
5. Происходит painting.

На этом ничего не заканчивается. Рендеринг - динамическая операция: некоторые шаги повторяются вновь и вновь, меняя структуру документа.

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

Одна из механик автоматической оптимизации - кэширование repainting-а и relayout-а: бразуер по возможности выполняет потоки команд, входящих в эти операции, едиными блоками.

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

Неизбежен, однако, риторический вопрос: почему сайты на Реакте такие тормозутые?..

#браузеры #рендеринг #React
React, заметки об архитектуре и другое:

- В идеале, каждый Реакт-компонент должен находиться в отдельном каталоге. Это роднит компонентный подход с БЭМ, где блок - не что иное как разбитая на собственные файлы структура.

- Файлы стилей должны называться так же, как и название компонента.

- В проекте отдельным каталогом должны содержаться юнит-тесты.

- C помощью Webpack можно укоротить пути к файлам компонентов (импортировать по-умолчанию). Для этого:
1. Создаем в папке компонента файл index.js (или с таким же названием, как корневой файл проекта)
2. Прописываем импорт и экспорт:
import MyComponent from './my-component';
export default MyComponent;
3. Убираем дублирование названия файла компонента в корневом файле проекта.
Если Webpack будет ругаться на отсутствие файлов, может помочь рестарт скриптов.

- Компоненты-классы от функциональных отличаются возможностью хранить состояние.

- Если импортировать компонент через деструктуризацию:
import React, { Component } from 'react'
...то не придётся писать в компоненте-классе extends React.Component: вместо этого можно будет написать просто Component.

- Экспортировать компоненты можно, объявляя export default прямо перед объявлениями этих компонентов.

#React #архитектура #webpack
React: безопастность и полезные приемы

- В Реакте нельзя напрямую обновлять State. Для этого используется функция setState. В неё напрямую можно передавать новые значения полей объекта State... Но не всегда это выбор джедая.

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

this.setState({
field: !this.state.field
})

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

Наилучший способ - передавать в setState другую функцию, которая будет получать Statе, когда тот тот уже полностью обновлен и готов принять противоположное значение:

this.setState(state => {
return {
field: !state.field
}
})

Короче: если метод ссылается на предыдущее значение поля - переключает true/false, увеличивает значение, меняет в зависимости от текущего, - надо передавать в setState функцию. Иначе можно просто передавать объект.

#React #приемы_разработки
React: кастомные события, иерархия и другое

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

На одном из звеньев мы ловим классическое DOM-событие вроде onClick, и кастомное событие обрабатывается.

Концепция однонаправленных потоков типов данных очень важна для Реакта и будет рассмотрена позже (наверное).

- Компонент-функцию можно легко переделать в класс, если переместить её JSX вместе с return в метод render класса.

- В новом JS появился метод массива findIndex. Возвращает элемент массива, соответствующий условию. Вкусный сахар.

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

- Если поле State - массив, и задача - удалить элемент, решение может быть таким:
1. Получаем любым немутабельным методом первую часть - от начала до удаляемого индекса.
2. Примерно так же получаем остаток - от удаляемого + 1 элемента до конца.
3. Склеиваем.
4. Возвращаем новый массив в State.

#React
React, заметки:

- React.Fragment - обертка для элементов, которая используется, когда нельзя использовать <div> - например, в списках и таблицах. Имеет коротку запись <> ... </> (пока поддерживается малым количеством инструментов, не рекомендуется).

- Жизненный цикл компонента в Реакт - это очередь событий, которые происходят с компонентом. Как и в WP, для этих событий есть хуки:

1. componentDidMount() - срабатывает, когда компонент отрендерен как ДОМ-объект.
2. componentDidUpdate() - срабатывает при обновлении состояния компонента. Используется, например, для получения данных по АПИ. Предпочтительно делать это в нём, а не в конструкторе.
3. componentWillUnmount - перед удалением ДОМ-элемента.
4. componentDidCatch() - ловит ошибку, под которую не подготовлен обработчик.

#React #жизненный_цикл
React: Error Boundaries

Реакт своеобразно обрабатывает ошибки UI: неправильное поведение хотя бы одного компонента рушит все приложение. Это похоже на 500-ю ошибку сервера. Обработчик формы написан неправильно, не указано никаких настроек дебага - и вы видите заглушку с ошибкой. Реакт и вовсе выводит на проде пустую страницу.

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

Что происходит с ошибкой в дереве компонентов? Она всплывает, пока не доберется до root. Error boundaries - это компоненты, в которые встроены обработчики ошибок, не дающие тем всплыть и уничтожить приложение. Для обработки используются метод жизненного цикла componentDiDCatch().

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

ComponentDidCatch работает только для методов жизненного цикла и рендеринга приложения. Ошибки в event listener-ах или асинхронных коллбеках он не ловит.

#React #обработка_ошибок #UX
React: разделение ответственности

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

Error boundaries тоже могут быть отделены от компонентов, занятых рендерингом. Для этого можно использовать props.children. В этом свойстве объекта props находится код, который написан между открывающим и закрывающим тегами компонента:

<Header>
<ChildComponent />
</Header>

Для обработки ошибок создаем компонент-обертку, которая возвращает своих "детей":

<ErrorBoundry>
<Header />
</ErrorBoundry>.

#React #паттерны #обработка_ошибок
Хуки Реакта: что, зачем и как

Что:
Хуки - это новое АПИ для модных функциональных пацанов (с), которое позволяет отказаться от компонентов-классов. Преимуществом классов была возможность использовать локальное состояние, но с хуками добавлять state можно и в функциональны компоненты. Не путать с хуками жизненного цикла!

Зачем:
1. Переиспользуемость. В классических компонентах для разделения состояния использовали, например, компоненты-обертки. С хуками все проще: пишем логику функциями в отдельном файле, импортируем, вызываем. Всё.
2. Простота. Официальный туториал утверждает: для Реакт-разработчков сложно усвоить правила работы this в JS. Мои соболезнования компаниям, где работают такие девелоперы. Тем не менее, возня с привязкой this сократилась с упрощенной до отсутствующей.

Как:
Все просто. Создаем через деструктуризацию пользовательнкую переменную и метод обновления:

const [age, setAge] = useState(42);

...И применяем, как ранее в классах. О тонкостях, типа useEffect, позже.

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

#React #хуки
Хуки Реакта-2: useEffect

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

Собственно эффект - это функция, которую и цепляет на себя хук.

Хук эффекта объединяет возможности методов жизненного цикла: componentDidMount, componentDidUpdate, componentWillUnount. Это поможет объединить похожую логику, разбитую в классах по методам жизненного цикла.

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

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

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

useEffect(() => {
document.title = `Вы нажали ${count} раз`;
}, [count]);

В этом случае эффект будет вызван, только если значение count изменится.

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

#React #хуки
React. Раунд 2!

Готовлюсь ко внутреннему собеседованию по фронту. А значит, время нам с вами повторить пройденное!

- JSX-сущность = результат вызова функции createElement = объект с полями props, children етц.
Если держать в голове этот факт, не забудешь, что вообще такое хреновы пропсы.

- Children - это, если очень грубо, все, что между тегами элемента. <h1> -> тут children <- </h1). Это просто потомки, как в HTML.

- Еще внутри объекта есть key, ref, _owner и не только.

- Корневых узлов может быть несколько.

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

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

#React
- Композиция в React - просто дробление UI на блоки. Больше блок - больше отдельных компонентов. Профит - переиспользуемость.

- Нельзя менять state в обход сеттера setState.

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

- Можно обновлять поля state независимо в отдельных вызовах.

- Вообще state - это как props, только инкапсулированный. Работать со стейтом может исключительно компонент, которому он принадлежит.

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

- Синтетическое событие - это обертка Реакта над стандартными событиями DOM. Используется для кроссбраузерности. Его интерфейс аналогичен стандартным событиям, имеется доступ и к оригинальным.

- Как передать аргумент в обработчик события? Поместить его в функцию-стрелку.
#React
Привязка контекста в React

В компонентах-классах мы передаем обработчики событий в дочерние компоненты. Однако они не выполняются.

Что происходит?
Передавая метод класса в render, мы выполняем примерно следующее:
const newMethod = obj.method
Представим, что метод возвращает что-то вроде "this.something". Что такое this? Это ссылка на контекст объекта. Когда мы присваиваем метод внешней переменной, то и контекст меняем тоже.

Как этого избежать?
Жестко привязать контекст метода к объекту. Для этого используем .bind(), стрелочные функции или замыкания. Старый добрый способ - привязать this в конструкторе:
this.methodName = this.methodName.bind(this).

Подробнее: https://learn-reactjs.ru/faq/passing-functions-to-components

#React