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

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

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

- Поток данных в Реакте идёт по нисходящей, от родителей к детям. Например, если компонент рендерит 9 более мелких компонентов, данные - пропсы - передаются от этого крупного компонента в мелкий, который и обрабатывает их. Так работает декларативность React.

- В обработчиках компонентов допустимы (и желательны) стрелочные функции.

- State - это "память" компонентов. Например, с помощью state компонент запоминает, что по нему кликнули.

- Без Redux state хранится прямо в компонентах, в кострукторе их классов. У функциональных компонентов state нет: они так и называются - stateless components.

- Как и в PHP, при объявлении конструктора класса-наследника нужно вызвать конструктор родителя. В JS это нужно делать до вызова собственного конструктора наследника.


#react
Принципы Реакт - продолжение:

- Контролируемые компоненты: это компоненты, полностью зависимые от родительских. У них нет своего state и, как правило, своих методов, кроме render. Их состояние хранится в родительских компонентах, а методы передаются через props.

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

- Атрибуты ref могут привести к выстроению императивной системы. Для React это антипаттерн. Об этом позже.

- Функциональные компоненты - способ проектирования Реакт-компонентов, у которых есть только метод render, а остальная информация передается через props. Это более быстрый и чистый способ написания контролируемых компонентов.

#react #функциональные_компоненты
JS - копирование объекта:

- Для копирования объектов есть функция assign. Как она работает:
- функция принадлежит объекту Oblect, поэтому вызывается через Object.assign().
- Она принимает параметры: target - единственный, source - множество, где:
1. target - объект, который возвратит функция.
2. source - объект, из которого копируются ключи-значения.

Пример с клонированием объекта:

let obj = { key: value }
let clone = Object.assign({}, obj)

Здесь функция копирует в пустой объект содержимое obj и присваивает пустой объект переменной clone. Source может быть и объект, определенный прямо в функции.

ВАЖНО: порядок указания sources задает приоритет перезаписи свойств при клонировании. Например в коде:

Object.assign({}, src1, src2)

src1 будет иметь больший приоритет, и если в src2 встретится свойство, аналогичное содержащемуся в src1, оно будет перезаписано свойством из src1.

Эта тема важна для понимания иммутабельности в React.

#JS #React
Выгоды иммутабельности в Реакт:

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

- Проще выполнить сложные задачи, такие как откат к состоянию, отделенному промежуточными операциями.

- Легко выполнять ре-рендеринг компонентов.

- Способствует созданию "чистых" компонентов.

#React #Иммутабельность
Реакт - заметка об элементах:

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

- props, key и другие важные сущности React - это просто ключи объектов, которыми под капотом являются элементы.



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

- Компоненты Реакт - это функции или классы, которые возвращают Реакт-элементы. Ничего больше.

- Компоненты Реакт "вызываются" в JSX, как обычные HTML-теги - не важно, функциональные это компоненты, классы или какие-либо другие.

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

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

- Переменные нельзя присвоить компонентам Реакт строкой, как атрибуты HTML. Они (переменные) передаются в атрибуты через фигурные скобки:
attr={styleObject}

- CSS можно передавать компонентам с помощью объектов-сборников правил.

- Любой код, использующий JSX, требует импорта React. Это обязательно.

- Любое свойство, которому не назначено значение, в JSX эквивалентно true.

- Без передачи props объект props все равно будет передан компоненту, но будет пустым.

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

function MyElement({ myAttr }) {
return <span>{myAttr}</span>
}

Обратите внимание, здесь не используется прямой путь до props (props.myAttr): вместо этого применяется деструктуризация props-объекта.

#React
React - cмысл Key:

В Реакт есть сущность - key. Это уникальный идентификатор реакт-компонента. Применяется, в частности, в построении списков при передаче массивов в качестве props.

Его задача - оптимизировать производительность. При перерисовке вирутального дом-дерева Реакт сравнивает между собой не компоненты, которые могут быть тяжеловесными, а только их key. Это похоже на механизм NodeJS для передачи больших файлов без их считывания или маркировку HTTP-пакетов легковесным заголовком. Таким образом Реакт выполняет меньше работы и работает еще быстрее.

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

Аналогичен результат с использованием индексов массивов как keys. Реакт и так по-умолчанию маркирует элементы нумерацией, а это непроизводительный способ.

#React
React - привязка методов

В классах Реакта можно заметить биндинг методов-обработчиков событий:

this.method = this.method.bind(this)

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

<element onClick=this.method>

Биндинг связывает this с контекстом класса, и контекст уже не теряется.

Есть и другие способы привязки this в классе. Подробнее:
https://getinstance.info/articles/react/react-and-es6-part3/

#React #JS
Тонкости импорта

В нативных модулях ES6 параметр import принимает строкой путь к модулю:

import React from 'react'

Этот путь может быть нескольких видов. Относительный и абсолютный используется по-умолчанию для кастомных модулей:
'./relativePath'
'/absolute/Path'/

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

Есть два предположения, почему так происходит:

1. Такой способ импорта допустим для встроенных модулей и библиотек со специфическими настройками;
2. Такой способ специфичен для Webpack.

А вы как думаете?

#JS #React
Спасибо всем, кто участвовал в опросе.
Верный вариант - специфика Webpack.

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

#JS #React #Webpack
Полезные практики в 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