Глубокое погружение в код React. Часть 2. Самые популярные пакеты
Глубокое погружение в код React. Часть 1. Вводная
Продолжаем разбор кодовой базы React (англ.): https://dev.to/fromaline/deep-dive-into-react-codebase-ep2-what-package-from-the-repo-is-the-most-popular-on-npm-2328
Вторая часть серии - это краткий обзор пакетов, входящих в состав монорепозитория React. Тут есть утилиты вроде react-is и scheduler, инструменты для разработчиков, включая плагин для ESLint, инструменты для тестирования, для создания подписок, а также несколько экспериментальных нестабильных пакетов.
Во второй части статьи автор приводит статистику использования по всем пакетам React. Оказывается, сам React (ядро проекта) находится только на третьем месте по количеству скачиваний. Его уверенно обходят утилиты (react-is и scheduler). На четвертом месте предсказуемо react-dom, на пятом - плагин для ESLint.
#ссылки #подкапотом
Глубокое погружение в код React. Часть 1. Вводная
Продолжаем разбор кодовой базы React (англ.): https://dev.to/fromaline/deep-dive-into-react-codebase-ep2-what-package-from-the-repo-is-the-most-popular-on-npm-2328
Вторая часть серии - это краткий обзор пакетов, входящих в состав монорепозитория React. Тут есть утилиты вроде react-is и scheduler, инструменты для разработчиков, включая плагин для ESLint, инструменты для тестирования, для создания подписок, а также несколько экспериментальных нестабильных пакетов.
Во второй части статьи автор приводит статистику использования по всем пакетам React. Оказывается, сам React (ядро проекта) находится только на третьем месте по количеству скачиваний. Его уверенно обходят утилиты (react-is и scheduler). На четвертом месте предсказуемо react-dom, на пятом - плагин для ESLint.
#ссылки #подкапотом
Разделение контекстов
Хук
Некоторые компоненты могут использовать только
Но это работает только если провайдеры контекстов вынесены в отдельный компонент, пока не могу понять, почему. Если содержимое приложения выводится внутри провайдеров как
Но если выводить что-то напрямую внутри провайдеров, то оно будет перерендериваться при любом изменении.
Как это работает?
Пример: https://codesandbox.io/s/separate-contexts-react-junior-p06kbr?file=/src/App.js
UPD: Ответ в следующем посте ⬇️
#управлениесостоянием #контекст #хуки #паттерны #вопросы
Хук
useReducer
возвращает объект состояния и функцию dispatch
для его изменения. При этом объект состояния, очевидно, постоянно изменяется, а вот функция dispatch
всегда одна и та же. Некоторые компоненты могут использовать только
dispatch
и не использовать состояние. Но если передавать их через один контекст, этим компонентам придется постоянно изменяться, хоть это и не нужно. Чтобы избежать этого, рекомендуется передавать состояние и dispatch
отдельно, через разные контексты.Но это работает только если провайдеры контекстов вынесены в отдельный компонент, пока не могу понять, почему. Если содержимое приложения выводится внутри провайдеров как
props.children
, то все нормально, лишних рендеров нет.
component Providers
return StateProvider
DispatchProvider
props.children
component App
return Providers
Components
Но если выводить что-то напрямую внутри провайдеров, то оно будет перерендериваться при любом изменении.
component Providers
return StateProvider
DispatchProvider
Components
Как это работает?
Пример: https://codesandbox.io/s/separate-contexts-react-junior-p06kbr?file=/src/App.js
UPD: Ответ в следующем посте ⬇️
#управлениесостоянием #контекст #хуки #паттерны #вопросы
CodeSandbox
Separate contexts. React Junior - CodeSandbox
Separate contexts. React Junior by furrycat.web using react, react-dom, react-scripts
👏1
Компоненты, вставленные через props.children, не обновляются при рендере родительского компонента
Разумеется, этим вопросом уже задавались люди до меня 🙂
Развернутый ответ: https://stackoverflow.com/questions/47567429/this-props-children-not-re-rendered-on-parent-state-change/57332409#57332409?newreg=c8b54a9215714a22b3d190c398e497f6
Исходная проблема
https://yangx.top/react_junior/257
Если перерендеривается родительский компонент
Решение
Компонент
А на обычном JavaScript это выглядит так:
Именно этот код запускается при каждом рендере компонента
Код для рендера компонента
Объект
Если же поместить
То есть при каждом рендере
Выводы
1. JSX очень расслабляет и заставляет забыть о реальном JavaScript, который работает под капотом.
2. Четко сформулировать проблему - большой шаг к ее решению.
3. Не может ли возникнуть других ошибок в этом месте, связанных с необновлением дочерних компонентов?
Можно ли без JSX: https://yangx.top/react_junior/30
#вопросы #подкапотом #ошибки #важно
Разумеется, этим вопросом уже задавались люди до меня 🙂
Развернутый ответ: https://stackoverflow.com/questions/47567429/this-props-children-not-re-rendered-on-parent-state-change/57332409#57332409?newreg=c8b54a9215714a22b3d190c398e497f6
Исходная проблема
https://yangx.top/react_junior/257
Если перерендеривается родительский компонент
Providers
, я ожидаю, что все дочерние компоненты тоже перерендерятся. Но те компоненты, которые пришли в props.children
не перерендериваются. Но если их прямо перенести в Providers
, то они перерендериваются, как и ожидается.Решение
Компонент
App
на JSX выглядит так (схематично):
Providers
Child
А на обычном JavaScript это выглядит так:
React.createElement(
Providers,
{},
React.createElement(
Child,
{},
{}
)
)
Именно этот код запускается при каждом рендере компонента
App
.Код для рендера компонента
Providers
же выглядит так:
React.createElement(
'div',
{ },
this.props.children
)
Объект
this.props.children
здесь всегда представлен одной и той же ссылкой, он не меняется, а значит у React нет причин перерендеривать его.Если же поместить
Child
напрямую в Providers
, мы код рендера Providers
изменится:
React.createElement(
'div',
{ },
React.createElement(
Child,
{},
{}
)
)
То есть при каждом рендере
Providers
будет вызываться вложенный метод React.createElement
, который будет возвращать каждый раз новый объект, который придется перерендеривать.Выводы
1. JSX очень расслабляет и заставляет забыть о реальном JavaScript, который работает под капотом.
2. Четко сформулировать проблему - большой шаг к ее решению.
3. Не может ли возникнуть других ошибок в этом месте, связанных с необновлением дочерних компонентов?
Можно ли без JSX: https://yangx.top/react_junior/30
#вопросы #подкапотом #ошибки #важно
Stack Overflow
this.props.children not re-rendered on parent state change
I have a piece of code
import React, {Component} from 'react';
class App extends Component {
render() {
return (
<Container>
<Child/>
</Container>
...
import React, {Component} from 'react';
class App extends Component {
render() {
return (
<Container>
<Child/>
</Container>
...
👏1
Оптимизация useReducer + useContext
Итак, с учетом свежих знаний оптимизация управления глобальным состоянием на хуках выглядит так:
https://codesandbox.io/s/usereducer-usecontext-optimization-react-junior-u5z6q7?file=/src/App.js
1. Используем разные контексты для передачи состояния и метода
2. Выносим провайдеры обоих контекстов в отдельный компонент-обертку и туда же помещаем вызов
Компоненты, которым важно следить за обновлением состояния, будут получать его из хука
#управлениесостоянием #хуки #оптимизация
Итак, с учетом свежих знаний оптимизация управления глобальным состоянием на хуках выглядит так:
https://codesandbox.io/s/usereducer-usecontext-optimization-react-junior-u5z6q7?file=/src/App.js
1. Используем разные контексты для передачи состояния и метода
dispatch
(и то, и то возвращается из хука useReducer
).2. Выносим провайдеры обоих контекстов в отдельный компонент-обертку и туда же помещаем вызов
useReducer
. Таким образом, при изменении состояния произойдет перерендер этого компонента, но вложенные компоненты не будут обновляться. (почему?)Компоненты, которым важно следить за обновлением состояния, будут получать его из хука
useContext
. #управлениесостоянием #хуки #оптимизация
CodeSandbox
useReducer + useContext optimization. React Junior - CodeSandbox
useReducer + useContext optimization. React Junior by furrycat.web using react, react-dom, react-scripts
👏1
Redux: начало
Начнем как всегда с начала, то есть с документации: https://redux.js.org/introduction/getting-started. Она, кстати, очень большая, с кучей разных туториалов и объяснений.
Итак, основные части Redux:
Хранилище (store)
Все глобальное состояние приложения хранится в одном месте в виде объекта. Его можно читать, но нельзя изменять напрямую.
Действия (actions)
Единственный способ внести изменение в store - действия. Действие - это объект, описывающий, что происходит. У него есть тип и (при необходимости) какие-то дополнительные данные (`payload`).
Редьюсер
Функция, которая принимает на вход объект действия, а возвращает обновленное состояние. Редьюсер инкапсулирует всю логику изменения. Таким образом, все действия отправляются в редьюсер.
Все это нам уже известно на примере встроенного хука
Создание хранилища
1. Определяемся со структурой состояния
2. Определяем, какие экшены доступны для его измнения
3. Создаем редьюсер, обрабатывающий эти экшены
4. Создаем объект хранилища с помощью метода
Взаимодействие с хранилищем
Чтение данных:
Подписка на изменения:
Отправка действия:
#управлениесостоянием #redux #документация #началоработы
Начнем как всегда с начала, то есть с документации: https://redux.js.org/introduction/getting-started. Она, кстати, очень большая, с кучей разных туториалов и объяснений.
Итак, основные части Redux:
Хранилище (store)
Все глобальное состояние приложения хранится в одном месте в виде объекта. Его можно читать, но нельзя изменять напрямую.
Действия (actions)
Единственный способ внести изменение в store - действия. Действие - это объект, описывающий, что происходит. У него есть тип и (при необходимости) какие-то дополнительные данные (`payload`).
Редьюсер
Функция, которая принимает на вход объект действия, а возвращает обновленное состояние. Редьюсер инкапсулирует всю логику изменения. Таким образом, все действия отправляются в редьюсер.
Все это нам уже известно на примере встроенного хука
useReducer
.Создание хранилища
1. Определяемся со структурой состояния
2. Определяем, какие экшены доступны для его измнения
3. Создаем редьюсер, обрабатывающий эти экшены
4. Создаем объект хранилища с помощью метода
createStore(reducer)
Взаимодействие с хранилищем
Чтение данных:
store.getState()
Подписка на изменения:
store.subscribe(cb)
Отправка действия:
store.dispatch(actionObject)
#управлениесостоянием #redux #документация #началоработы
redux.js.org
Getting Started with Redux | Redux
Introduction > Getting Started: Resources to get started learning and using Redux
👏1
Redux не связан с React
Самый базовый пример работы Redux, без React - только ванильный JS + HTML (чтобы не было никакого волшебства):
https://codesandbox.io/s/redux-basic-forked-react-junior-ud3hq0?file=/index.js
Здесь используются все основные концепции:
- создание хранилища с редьюсером
- подписка на обновления
- получение данных из хранилища
- диспатч экшенов для изменения
Вообще Redux самостоятельная библиотека, не привязанная к какому-либо фреймворку. Она маленькая сама по себе (2kB), но кроме ядра (redux) нам понадобятся дополнительные функции, чтобы связать redux и react (пакет react-redux).
Теоретически эту связку можно было бы написать самостоятельно, скорее всего, ничего сложного там нет, используются уже разобранные функции redux (подписка на хранилище), но зачем, если есть уже готовый производительный оттестированный пакет.
Вот пример из документации, где react работает вместе с redux без дополнительных биндингов: https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/counter?from-embed=&file=/src/index.js
Здесь просто на каждое изменение хранилища вручную вызывается
#управлениесостоянием #примерыкода #redux
Самый базовый пример работы Redux, без React - только ванильный JS + HTML (чтобы не было никакого волшебства):
https://codesandbox.io/s/redux-basic-forked-react-junior-ud3hq0?file=/index.js
Здесь используются все основные концепции:
- создание хранилища с редьюсером
- подписка на обновления
- получение данных из хранилища
- диспатч экшенов для изменения
Вообще Redux самостоятельная библиотека, не привязанная к какому-либо фреймворку. Она маленькая сама по себе (2kB), но кроме ядра (redux) нам понадобятся дополнительные функции, чтобы связать redux и react (пакет react-redux).
Теоретически эту связку можно было бы написать самостоятельно, скорее всего, ничего сложного там нет, используются уже разобранные функции redux (подписка на хранилище), но зачем, если есть уже готовый производительный оттестированный пакет.
Вот пример из документации, где react работает вместе с redux без дополнительных биндингов: https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/counter?from-embed=&file=/src/index.js
Здесь просто на каждое изменение хранилища вручную вызывается
ReactDOM.render
.#управлениесостоянием #примерыкода #redux
CodeSandbox
Redux basic (forked). React Junior - CodeSandbox
Redux basic (forked). React Junior by furrycat.web
👏3
Связка React-Redux
Мы уже констатировали, что Redux - это абсолютно самостоятельная библиотека. У нее есть API, с помощью которого ее можно подключить к любому приложению, на любом фреймворк или без него.
Так как наши интересы сосредоточены на React, мы обратимся к связке React + Redux. Не будем изобретать велосипедов и возьмем готовый пакет react-redux.
Что у нас тут есть?
🔸 1. Создание хранилища
Это сфера ответственности Redux, тут никаких специальных методов не требуется.
🔸 2. Получение данных из хранилища
Передача данных из хранилища в приложение в react-redux работает по модели контекста. Все приложение оборачивается в компонент
🔸 3. dispatch
Чтобы отправить экшен в хранилище, есть хук
Итак, все базовые функции есть, можно создать простенькое приложение.
Приложение
https://codesandbox.io/s/react-redux-react-junior-w6ey1n?file=/src/App.js
Стандартная "тудушка", с массивом элементов и возможностью добавить/отредактировать/удалить их.
В глобальное состояние вынесен только массив элементов (
Использованные пакеты: redux, react-redux.
#управлениесостоянием #redux #началоработы #примерыкода
Мы уже констатировали, что Redux - это абсолютно самостоятельная библиотека. У нее есть API, с помощью которого ее можно подключить к любому приложению, на любом фреймворк или без него.
Так как наши интересы сосредоточены на React, мы обратимся к связке React + Redux. Не будем изобретать велосипедов и возьмем готовый пакет react-redux.
Что у нас тут есть?
🔸 1. Создание хранилища
Это сфера ответственности Redux, тут никаких специальных методов не требуется.
🔸 2. Получение данных из хранилища
Передача данных из хранилища в приложение в react-redux работает по модели контекста. Все приложение оборачивается в компонент
Provider
, а в заинтересованных компонентах нужно использовать хук useSelector
, чтобы получить доступ к хранилищу. Этот хук принимает функцию-селектор. При каждом изменении хранилища она вызывается, получает текущее состояние в качестве аргумента и может надергать из него все, что нужно.🔸 3. dispatch
Чтобы отправить экшен в хранилище, есть хук
useDispatch
, работает точно так же, как метод store.dispatch
(это он и есть, в общем).Итак, все базовые функции есть, можно создать простенькое приложение.
Приложение
https://codesandbox.io/s/react-redux-react-junior-w6ey1n?file=/src/App.js
Стандартная "тудушка", с массивом элементов и возможностью добавить/отредактировать/удалить их.
В глобальное состояние вынесен только массив элементов (
items
), состояние инпута для ввода текста хранится локально в компоненте.Использованные пакеты: redux, react-redux.
#управлениесостоянием #redux #началоработы #примерыкода
CodeSandbox
React + Redux. React Junior - CodeSandbox
React + Redux. React Junior by furrycat.web using nanoid, react, react-dom, react-redux, react-scripts, redux
Селекторы и ререндеринг при изменении данных
В нашем приложении есть одна проблема.
В компоненте
Даже если мы изменяем только поле
Но можно решить эту проблему. Хук
Изменим код приложения. В компоненте
А для списка добавим функцию сравнения, которая будет проверять, не отличается ли новый набор идентификаторов от старого.
Но можно не писать функцию сравнения самому, а взять уже готовую
После этого рефакторинга список перерендеривается только при добавлении/удалении элементов, а отдельные элементы сами отвечают за свое состояние.
https://codesandbox.io/s/react-redux-equalityfn-react-junior-4ne0m5?file=/src/components/List/index.js
#управлениесостоянием #redux #началоработы #примерыкода #производительность #важно
В нашем приложении есть одна проблема.
В компоненте
List
мы получаем из state
список элементов с помощью функции-селектора. Из-за того что редьюсер является чистой функцией, при каждом изменении этот список копируется, то есть в селекторе получается каждый раз НОВЫЙ массив. Хук useSelector
сравнивает его с предыдущим значением, считает, что произошли изменения, и перерендеривает весь компонент List
.Даже если мы изменяем только поле
completed
у одного элемента, перерендеривается весь список, что не очень хорошо.Но можно решить эту проблему. Хук
useSelector
принимает второй аргумент - функцию сравнения. По умолчанию используется просто строгое сравнение ===
предыдущего и нового значения, но мы можем изменить это, передав собственную функцию, которая будет определять, произошли ли измнения на самом деле.Изменим код приложения. В компоненте
List
будем получать только список идентификаторов элементов, чтобы понять, не изменился ли состав списка. А получение собственно данных перенесем в компонент Item
. То есть каждый элемент будет самостоятельно запрашивать данные для своего отображения (текст и флаг completed`), зная только свой `id
. Таким образом, если если данные элемента изменятся, то перерендерится только он один.А для списка добавим функцию сравнения, которая будет проверять, не отличается ли новый набор идентификаторов от старого.
const selector = function (state) {
return state.items.map(function(item) {
return item.id;
});
};
const equalityFn = function (newState, oldState) {
return JSON.stringify(newState) === JSON.stringify(oldState);
}
//...
const items = useSelector(selector, equalityFn);
Но можно не писать функцию сравнения самому, а взять уже готовую
shallowEqual
из пакета react-redux.После этого рефакторинга список перерендеривается только при добавлении/удалении элементов, а отдельные элементы сами отвечают за свое состояние.
https://codesandbox.io/s/react-redux-equalityfn-react-junior-4ne0m5?file=/src/components/List/index.js
#управлениесостоянием #redux #началоработы #примерыкода #производительность #важно
Telegram
React Junior
Связка React-Redux
Мы уже констатировали, что Redux - это абсолютно самостоятельная библиотека. У нее есть API, с помощью которого ее можно подключить к любому приложению, на любом фреймворк или без него.
Так как наши интересы сосредоточены на React, мы…
Мы уже констатировали, что Redux - это абсолютно самостоятельная библиотека. У нее есть API, с помощью которого ее можно подключить к любому приложению, на любом фреймворк или без него.
Так как наши интересы сосредоточены на React, мы…
Action Creators
Один из паттернов, который рекомендует нам документация Redux, - это Создатели Экшенов.
То есть мы не передаем в
Это удобно, так как не нужно запоминать структуру экшена, функция сгенерирует его самостоятельно, кроме того, в такую функцию можно передать параметры. Здесь же можно инкапсулировать какую-нибудь логику обработки этих параметров. И наконец, создатели экшенов облегчают работу с асинхронными изменениями данных (об этом поговорим позже).
#управлениесостоянием #redux #началоработы #документация
Один из паттернов, который рекомендует нам документация Redux, - это Создатели Экшенов.
То есть мы не передаем в
dispatch
объект действия напрямую, а вызываем функцию, которая нам его создает.Это удобно, так как не нужно запоминать структуру экшена, функция сгенерирует его самостоятельно, кроме того, в такую функцию можно передать параметры. Здесь же можно инкапсулировать какую-нибудь логику обработки этих параметров. И наконец, создатели экшенов облегчают работу с асинхронными изменениями данных (об этом поговорим позже).
#управлениесостоянием #redux #началоработы #документация
Разделение редьюсеров
Еще один хороший прием - разделение одного редьюсера на несколько. Для каждой части приложения свой.
Добавим, например, к нашей учебной тудушке фильтр по статусу задачи, чтобы можно было выводить отдельно завершенные и незавершенные дела.
https://codesandbox.io/s/react-redux-combine-reducers-react-junior-ry72g1
У хранилища Redux может быть только один редьюсер, но когда экшенов становится очень много, его трудно поддерживать. Поэтому один редьюсер можно разделить на несколько. В данном случае - один редьюсер для всего, что связано со списком дел (сам список, добавление, удаление, изменение статуса), и второй для фильтров (которых может быть много).
У меня они находятся в папках store/filters и store/items. Документация предлагает делить немного по-другому, но это нужно будет отдельно разобрать.
Перед созданием хранилища нужно собрать два редьюсера в один:
В итоге у нас получится объект хранилища с двумя полями -
Вместо ручного объединения лучше использовать готовую функцию
#управлениесостоянием #redux #началоработы #примерыкода #документация
Еще один хороший прием - разделение одного редьюсера на несколько. Для каждой части приложения свой.
Добавим, например, к нашей учебной тудушке фильтр по статусу задачи, чтобы можно было выводить отдельно завершенные и незавершенные дела.
https://codesandbox.io/s/react-redux-combine-reducers-react-junior-ry72g1
У хранилища Redux может быть только один редьюсер, но когда экшенов становится очень много, его трудно поддерживать. Поэтому один редьюсер можно разделить на несколько. В данном случае - один редьюсер для всего, что связано со списком дел (сам список, добавление, удаление, изменение статуса), и второй для фильтров (которых может быть много).
У меня они находятся в папках store/filters и store/items. Документация предлагает делить немного по-другому, но это нужно будет отдельно разобрать.
Перед созданием хранилища нужно собрать два редьюсера в один:
const rootReducer = function(state = {}, action) {
return {
items: itemsReducer(state.items, action),
filters: filtersReducer(state.filters, action)
};
};
В итоге у нас получится объект хранилища с двумя полями -
items
и filters
, за каждое из которых отвечает свой собственный редьюсер.Вместо ручного объединения лучше использовать готовую функцию
combineReducers
из пакета react-redux.#управлениесостоянием #redux #началоработы #примерыкода #документация
CodeSandbox
React + Redux. Combine Reducers. React Junior - CodeSandbox
React + Redux. Combine Reducers. React Junior by furrycat.web using nanoid, react, react-dom, react-redux, react-scripts, redux
Префиксы в экшенах
При разделении приложения на несколько "фич" рекомендуется использовать префиксы в типах экшенов. Вместо
#redux #управлениесостоянием
При разделении приложения на несколько "фич" рекомендуется использовать префиксы в типах экшенов. Вместо
addItem
- items
/addItem
.#redux #управлениесостоянием
Упрощенный код хранилища Redux
1. В функцию создания хранилища
2. После создания вызывается инициализирующий экшен
#управлениесостоянием #redux #примерыкода #документация
function createStore(reducer, preloadedState) {
let state = preloadedState
const listeners = []
function getState() {
return state
}
function subscribe(listener) {
listeners.push(listener)
return function unsubscribe() {
const index = listeners.indexOf(listener)
listeners.splice(index, 1)
}
}
function dispatch(action) {
state = reducer(state, action)
listeners.forEach(listener => listener())
}
dispatch({ type: '@@redux/INIT' })
return { dispatch, subscribe, getState }
}
1. В функцию создания хранилища
createStore
можно передать исходное состояние - параметр preloadedState
2. После создания вызывается инициализирующий экшен
#управлениесостоянием #redux #примерыкода #документация
Создаем свой React с рендером и useState за 30 минут
Пишем собственную реализацию React, чтобы понять, что там под капотом.
Статья (рус.): https://habr.com/ru/post/652487/
Спойлер: React будет урезанный, только рендер и хук useState, без виртуального DOM и согласования изменений
1. Настройка проекта с использованием parcel и typescript для компиляции JSX.
2. Реализация
3. Реализация метода для ререндера.
4. Реализация
В итоге получается нечто, что примерно соотствествует формуле React: интерфейс - это функция от состояния. Но без всяких оптимизаций.
Почитать интересно, чтобы еще раз это в голове уложить.
#ссылки #подкапотом
Пишем собственную реализацию React, чтобы понять, что там под капотом.
Статья (рус.): https://habr.com/ru/post/652487/
Спойлер: React будет урезанный, только рендер и хук useState, без виртуального DOM и согласования изменений
1. Настройка проекта с использованием parcel и typescript для компиляции JSX.
2. Реализация
React.createElement
и ReactDOM.render
для создания HTML-разметки из JSX.3. Реализация метода для ререндера.
4. Реализация
useState
с сохранением состояния между рендерами.В итоге получается нечто, что примерно соотствествует формуле React: интерфейс - это функция от состояния. Но без всяких оптимизаций.
Почитать интересно, чтобы еще раз это в голове уложить.
#ссылки #подкапотом
Road Map ReactJS-разработчика в 2022 году
Статья (англ.): https://medium.com/javarevisited/the-2019-react-js-developer-roadmap-9a8e290b8a56
В статье много ссылок на разные курсы (на англ.), но главное, она помогает создать общее впечатление об экосистеме и понять, куда двигаться.
Плюс, тут есть несколько ссылок на статьи с подборками источников знаний:
🔸 6 Best Websites to Learn React.js Coding for FREE in 2022
🔸 6 Best React.js Books for Beginners and Experienced Web Developers
🔸 Top 10 Online Courses to Learn React.js in Depth — Best of Lot
Итак, что должен изучить хороший React-разработчик?
✔️ 1. Основы (HTML, CSS, JS)
Без базовых знаний, понятно, никуда.
✔️ 2. Базовые скиллы разработчика
Тут и инструменты: Git, HTTP(S)-протокол со всеми основными методами (GET, POST, ...), работа с терминалом.
и теория: алгоритмы, структуры данных, шаблоны проектирования.
Действительно, в React (да и в любом инструменте в принципе) проще разобраться, когда ты понимаешь, что происходит.
✔️ 3. React JS
Ну, конечно, нельзя стать React-разработчиком, не изучив React JS.
✔️ 4. Инструменты сборки
React - современный инструмент, который использует под капотом много технологий, поэтому необходимо особым образом организовывать свои проекты, чтобы они работали в реальных условиях, например, в браузере. Для этого нужно знать, что такое менеджеры пакетов (npm, yarn, ...) и сборщики (webpack, parcel, rollup, gulp...).
✔️ 5. Стилизация
React поддерживает множество подходов к стилизации компонентов (это мы уже проходили https://yangx.top/react_junior/142), и нужно иметь о них представление. Но автор статьи советует начать с Bootstrap.
✔️ 6. Управление состоянием
Состояние - важная концепция в React, поэтому его изучаем отдельно (да, мы так и делаем). В списке технологий: контекст, redux с кучей доп. пакетов), mobx, ...
✔️ 7. Проверка типов
Нужна, чтобы избежать многочисленных ошибок. Речь, прежде всего, о TypeScript.
✔️ 8. Обработка форм
Грамотная работа с формами - очень важная часть разработки, к счастью, у нас есть множество инструментов для этого (redux form, formik, formsy, final form).
✔️ 9. Маршрутизация
Необходима для создания API. Обеспечивается React Router https://yangx.top/react_junior/230.
✔️ 10. Клиенты API
Клиентские приложения чаще всего не изолированы от внешнего мира и работают в связке с сервером, поэтому нам нужны инструменты для обеспечения этой связки (от fetch до graphql).
✔️ 11. Вспомогательные библиотеки
Инструменты, которые берут на себя отдельные задачи и облегчают жизнь разработчика. В списке: Lodash, Moment, Classnames, ...
✔️ 12. Тестирование
Все знают, что тестирование очень важно. И у нас тут огромное количество инструментов для разных видов тестирования.
✔️ 13. Интернационализация
Очень комплексная задача, для решения которой тоже есть готовые инструменты (react intl, react i18next)
✔️ 14. SSR
Первым в списке идет Next.js, и автор считает, что этого достаточно (по крайней мере, для начала)
✔️ 15. Генераторы статических сайтов
Тут только Gatsby.js
✔️ 16. Интеграция с бэкенд-фреймворками
Например, React on Rails для интеграции с Rails.
✔️ 17. Мобильная разработка
React может работать не только в вебе. Для мобильной разработки предлагается React Native.
✔️ 18. Разработка для Desktop
Для десктопной разработки тоже есть решения: Proton Native, Electron, React Native Windows.
✔️ 19. Виртуальная реальность
Тут React 360.
#ссылки #инструменты
Статья (англ.): https://medium.com/javarevisited/the-2019-react-js-developer-roadmap-9a8e290b8a56
В статье много ссылок на разные курсы (на англ.), но главное, она помогает создать общее впечатление об экосистеме и понять, куда двигаться.
Плюс, тут есть несколько ссылок на статьи с подборками источников знаний:
🔸 6 Best Websites to Learn React.js Coding for FREE in 2022
🔸 6 Best React.js Books for Beginners and Experienced Web Developers
🔸 Top 10 Online Courses to Learn React.js in Depth — Best of Lot
Итак, что должен изучить хороший React-разработчик?
✔️ 1. Основы (HTML, CSS, JS)
Без базовых знаний, понятно, никуда.
✔️ 2. Базовые скиллы разработчика
Тут и инструменты: Git, HTTP(S)-протокол со всеми основными методами (GET, POST, ...), работа с терминалом.
и теория: алгоритмы, структуры данных, шаблоны проектирования.
Действительно, в React (да и в любом инструменте в принципе) проще разобраться, когда ты понимаешь, что происходит.
✔️ 3. React JS
Ну, конечно, нельзя стать React-разработчиком, не изучив React JS.
✔️ 4. Инструменты сборки
React - современный инструмент, который использует под капотом много технологий, поэтому необходимо особым образом организовывать свои проекты, чтобы они работали в реальных условиях, например, в браузере. Для этого нужно знать, что такое менеджеры пакетов (npm, yarn, ...) и сборщики (webpack, parcel, rollup, gulp...).
✔️ 5. Стилизация
React поддерживает множество подходов к стилизации компонентов (это мы уже проходили https://yangx.top/react_junior/142), и нужно иметь о них представление. Но автор статьи советует начать с Bootstrap.
✔️ 6. Управление состоянием
Состояние - важная концепция в React, поэтому его изучаем отдельно (да, мы так и делаем). В списке технологий: контекст, redux с кучей доп. пакетов), mobx, ...
✔️ 7. Проверка типов
Нужна, чтобы избежать многочисленных ошибок. Речь, прежде всего, о TypeScript.
✔️ 8. Обработка форм
Грамотная работа с формами - очень важная часть разработки, к счастью, у нас есть множество инструментов для этого (redux form, formik, formsy, final form).
✔️ 9. Маршрутизация
Необходима для создания API. Обеспечивается React Router https://yangx.top/react_junior/230.
✔️ 10. Клиенты API
Клиентские приложения чаще всего не изолированы от внешнего мира и работают в связке с сервером, поэтому нам нужны инструменты для обеспечения этой связки (от fetch до graphql).
✔️ 11. Вспомогательные библиотеки
Инструменты, которые берут на себя отдельные задачи и облегчают жизнь разработчика. В списке: Lodash, Moment, Classnames, ...
✔️ 12. Тестирование
Все знают, что тестирование очень важно. И у нас тут огромное количество инструментов для разных видов тестирования.
✔️ 13. Интернационализация
Очень комплексная задача, для решения которой тоже есть готовые инструменты (react intl, react i18next)
✔️ 14. SSR
Первым в списке идет Next.js, и автор считает, что этого достаточно (по крайней мере, для начала)
✔️ 15. Генераторы статических сайтов
Тут только Gatsby.js
✔️ 16. Интеграция с бэкенд-фреймворками
Например, React on Rails для интеграции с Rails.
✔️ 17. Мобильная разработка
React может работать не только в вебе. Для мобильной разработки предлагается React Native.
✔️ 18. Разработка для Desktop
Для десктопной разработки тоже есть решения: Proton Native, Electron, React Native Windows.
✔️ 19. Виртуальная реальность
Тут React 360.
#ссылки #инструменты
👍1
Расширение функциональности
Итак, мы имеем примерное представление об устройстве и работе хранилища в Redux https://yangx.top/react_junior/268.
Если встроенной функциональности нам недостаточно, то ее можно расширить. Для этого существуют так называемые store enhancers (усилители, энхансеры, не знаю, как назвать).
Проект: https://codesandbox.io/s/react-redux-enhancers-react-junior-j20kqm?file=/src/App.js
Энхансер оборачивает функцию
Структура энхансера
Энхансер - это декоратор. Он оборачивает функцию
То же самое можно сделать с методами
Использование энхансеров
Чтобы применить энхансер, его нужно передать в метод
Если энхансеров несколько, то их нужно объединить в один с помощью функции
#управлениесостоянием #redux #началоработы #примерыкода
Итак, мы имеем примерное представление об устройстве и работе хранилища в Redux https://yangx.top/react_junior/268.
Если встроенной функциональности нам недостаточно, то ее можно расширить. Для этого существуют так называемые store enhancers (усилители, энхансеры, не знаю, как назвать).
Проект: https://codesandbox.io/s/react-redux-enhancers-react-junior-j20kqm?file=/src/App.js
Энхансер оборачивает функцию
createStore
(как декоратор) и может изменить возвращаемый объект хранилища, например, создать собственные методы dispatch
, subscribe
или getState
.Структура энхансера
Энхансер - это декоратор. Он оборачивает функцию
createStore
, а значит должен вернуть функцию с такой же сигнатурой - замену оригинальной createStore
. В свою очередь эта функция должна вернуть объект хранилища со всеми необходимыми методами.
export const logDispatch = function(createStore) {
return function(rootReducer, preloadedState, enhancers) {
const store = createStore(rootReducer, preloadedState, enhancers)
function newDispatch(action) {
const result = store.dispatch(action)
console.log('Dispach:', { action, result })
return result
}
return { ...store, dispatch: newDispatch }
}
}
То же самое можно сделать с методами
subscribe
и getState
, но dispatch
, наверно, чаще изменяют таким способом.Использование энхансеров
Чтобы применить энхансер, его нужно передать в метод
createStore
третьим аргументом (после редьюсера и preloadedState`). Если `preloadedState
не указывается, то его можно опустить, тогда энхансер станет вторым аргументом.Если энхансеров несколько, то их нужно объединить в один с помощью функции
compose
.
import { compose, createStore } from "redux";
const composedEnhancer = compose(logDispatch, logGetState, logSubscribe);
const store = createStore(rootReducer, composedEnhancer);
#управлениесостоянием #redux #началоработы #примерыкода
Telegram
React Junior
Упрощенный код хранилища Redux
function createStore(reducer, preloadedState) {
let state = preloadedState
const listeners = []
function getState() {
return state
}
function subscribe(listener) {
listeners.push(listener)
return function…
function createStore(reducer, preloadedState) {
let state = preloadedState
const listeners = []
function getState() {
return state
}
function subscribe(listener) {
listeners.push(listener)
return function…
👍2👏1
Redux предоставляет нам один готовый энхансер -
Таким образом, мы можем логировать экшены, изменять их, а также - самое главное - выполнять различные асинхронные операции, связанные с полученным экшеном.
Структура миддлвара
У миддвара сложная структура - это целых три вложенных друг в друга функции. Две первые - обертки, которые выполняются только один раз при создании. Они нужны для передачи важных аргументов (методов хранилища и следующего миддлвара в цепочке), а третья - это непосредственно та функция, которая будет обрабатывать конкретный экшен, когда он будет вызван.
Использование миддлваров
Функция
При этом каждый миддлвар может прервать цепочку, если не вызовет метод
Функция
Для примера подключим просто несколько логгеров. При каждой отправке экшена они будут выводить в консоль сообщение.
https://codesandbox.io/s/react-redux-middleware-react-junior-obvtcs?file=/src/store/index.js
#управлениесостоянием #redux #началоработы #примерыкода #документация
applyMiddleware
. Он работает с методом dispatch
хранилища, то есть на участке между получением экшена и его реальной отправкой в редьюсер.Таким образом, мы можем логировать экшены, изменять их, а также - самое главное - выполнять различные асинхронные операции, связанные с полученным экшеном.
Структура миддлвара
У миддвара сложная структура - это целых три вложенных друг в друга функции. Две первые - обертки, которые выполняются только один раз при создании. Они нужны для передачи важных аргументов (методов хранилища и следующего миддлвара в цепочке), а третья - это непосредственно та функция, которая будет обрабатывать конкретный экшен, когда он будет вызван.
function exampleMiddleware(storeAPI) {
return function wrapDispatch(next) {
return function handleAction(action) {
return next(action)
}
}
}
Использование миддлваров
Функция
applyMiddleware
принимает неограниченное количество аргументов - миддлваров - функций для обработки экшена и выстраивает из них пайплайн. То есть экшен отправится сначала в первый миддлвар, потом во второй, и так далее по цепочке, пока не дойдет до самого метода store.dispatch
.При этом каждый миддлвар может прервать цепочку, если не вызовет метод
next
.Функция
applyMiddleware
- это обычный энхансер, значит, мы уже знаем, как ее подключить к хранилищу.Для примера подключим просто несколько логгеров. При каждой отправке экшена они будут выводить в консоль сообщение.
https://codesandbox.io/s/react-redux-middleware-react-junior-obvtcs?file=/src/store/index.js
#управлениесостоянием #redux #началоработы #примерыкода #документация
CodeSandbox
React + Redux. Middleware. React Junior - CodeSandbox
React + Redux. Middleware. React Junior by furrycat.web using nanoid, react, react-dom, react-redux, react-scripts, redux
👍2👏1
Зачем нужны миддлвары?
В миддлвары следует помещать весь код с сайд-эффектами, связанный с обработкой экшенов. Тот код, который нельзя поместить в редьюсер, и как-то не очень хочется помещать в компонент.
- логирование
- запросы к серверу и другой асинхронный API
- маршрутизацию приложения
- изменение экшенов
- задержка выполнения (или прекращение)
https://codesandbox.io/s/react-redux-async-actions-react-junior-t2npxd?file=/src/store/checking/index.js
Добавим в наше приложение проверку текста новой задачи перед ее добавлением в список. Представим, что у нас есть какой-то api (асинхронный), который умеет анализировать текст. Если задача полезная, будем выводить поощрительное сообщение, а если нет - то осуждающее (и не будем добавлять эту задачу в список).
Для этого:
- добавляем новый редьюсер (
- добавляем компонент
- создаем миддлвар
#управлениесостоянием #redux #началоработы #примерыкода #документация
В миддлвары следует помещать весь код с сайд-эффектами, связанный с обработкой экшенов. Тот код, который нельзя поместить в редьюсер, и как-то не очень хочется помещать в компонент.
- логирование
- запросы к серверу и другой асинхронный API
- маршрутизацию приложения
- изменение экшенов
- задержка выполнения (или прекращение)
https://codesandbox.io/s/react-redux-async-actions-react-junior-t2npxd?file=/src/store/checking/index.js
Добавим в наше приложение проверку текста новой задачи перед ее добавлением в список. Представим, что у нас есть какой-то api (асинхронный), который умеет анализировать текст. Если задача полезная, будем выводить поощрительное сообщение, а если нет - то осуждающее (и не будем добавлять эту задачу в список).
Для этого:
- добавляем новый редьюсер (
checkingReducer
) и набор экшенов (START_CHECKING
, FINISH_CHECKING
, SET_CHECKING_STATUS
;- добавляем компонент
CheckingStatus
, который отслеживает статус проверки и выводит сообщение;- создаем миддлвар
checkText
, который реагирует только на события добавления нового элемента в список. Он останавливает цепочку обработки экшена и отправляет запрос на проверку текста. Только после окончания проверки он запускает цепочку обработки дальше (если нет ошибки), и экшен отправляется в редьюсер.#управлениесостоянием #redux #началоработы #примерыкода #документация
CodeSandbox
React + Redux. Async actions. React Junior - CodeSandbox
React + Redux. Async actions. React Junior by furrycat.web using nanoid, react, react-dom, react-redux, react-scripts, redux
👍1
Экшены-функции
Еще один вариант - переместить код, связанный с экшеном в функцию-создатель экшена. Но тут есть проблема - у функций-создателей нет доступа к методу
Эту задачу тоже можно решить с помощью миддлваров. Нужно сделать так, чтобы вместо объекта экшена будет можно было отправлять функцию, а этой функции при отправке передать
https://codesandbox.io/s/react-redux-functional-actions-react-junior-zyleg0?file=/src/store/items/actions.js
#управлениесостоянием #redux #началоработы #примерыкода #документация
Еще один вариант - переместить код, связанный с экшеном в функцию-создатель экшена. Но тут есть проблема - у функций-создателей нет доступа к методу
store.dispatch
.Эту задачу тоже можно решить с помощью миддлваров. Нужно сделать так, чтобы вместо объекта экшена будет можно было отправлять функцию, а этой функции при отправке передать
dispatch
в качестве аргумента. Тогда она уже сама разберется, когда и как отправлять экшены.https://codesandbox.io/s/react-redux-functional-actions-react-junior-zyleg0?file=/src/store/items/actions.js
const handleFunction = function(storeAPI) {
return function(next) {
return function(action) {
if (typeof action === 'function') {
return action(storeAPI.dispatch, storeAPI.getState)
}
return next(action)
}
}
}
#управлениесостоянием #redux #началоработы #примерыкода #документация
CodeSandbox
React + Redux. Functional actions. React Junior - CodeSandbox
React + Redux. Functional actions. React Junior by furrycat.web using nanoid, react, react-dom, react-redux, react-scripts, redux
👍1
Thunk
И наконец, у Redux есть официальный миддлвар для обработки функциональных экшенов - пакет redux-thunk. Можно заменить нашу самописную
https://codesandbox.io/s/react-redux-thunk-react-junior-d71jls?file=/src/store/index.js
#управлениесостоянием #redux #началоработы #примерыкода #документация
И наконец, у Redux есть официальный миддлвар для обработки функциональных экшенов - пакет redux-thunk. Можно заменить нашу самописную
handleFunction
на него:https://codesandbox.io/s/react-redux-thunk-react-junior-d71jls?file=/src/store/index.js
#управлениесостоянием #redux #началоработы #примерыкода #документация
CodeSandbox
React + Redux. Thunk. React Junior - CodeSandbox
React + Redux. Thunk. React Junior by furrycat.web using nanoid, react, react-dom, react-redux, react-scripts, redux, redux-thunk
👍1
Redux: документация и туториалы
У Redux реально огромная и максимально подробная документация. Помимо прочего, там есть два официальных туториала:
* Redux Essentials - изучение сверху вниз, демонстрация лучших практик и распространенных кейсов.
* Redux Fundamentals - изучение снизу вверх, от основ, для лучшего понимания.
Мы, разумеется, начали снизу вверх, как я люблю)) Сначала основы, потом лучшие практики.
#redux #документация
У Redux реально огромная и максимально подробная документация. Помимо прочего, там есть два официальных туториала:
* Redux Essentials - изучение сверху вниз, демонстрация лучших практик и распространенных кейсов.
* Redux Fundamentals - изучение снизу вверх, от основ, для лучшего понимания.
Мы, разумеется, начали снизу вверх, как я люблю)) Сначала основы, потом лучшие практики.
#redux #документация
redux.js.org
Getting Started with Redux | Redux
Introduction > Getting Started: Resources to get started learning and using Redux