Location State
В примере с аутентификацией использовалось некое "состояние Location", чтобы сохранить, на какую страницу пользователь хотел попасть, когда открылась форма авторизации. Разберемся с ним чуть подробнее.
У объекта
Однако в сигнатуре этого метода три параметра, и урл - последний из них и необязательный. Первым идет
Получить текущее состояние можно из
React Router позволяет удобно пользоваться этой фишкой прямо из объекта
Чтобы установить state для location, можно использовать проп
Чтобы получить текущий state, нужно использовать хук
Кейсы для использования:
- сохранение предыдущей локации для последующего перенаправления
- отправка данных (обычно урезанных, самых необходимых) для быстрого отображения на новой локации, пока основные данные загружаются
#роутинг #документация #паттерны
В примере с аутентификацией использовалось некое "состояние Location", чтобы сохранить, на какую страницу пользователь хотел попасть, когда открылась форма авторизации. Разберемся с ним чуть подробнее.
У объекта
window.history
в браузере есть метод pushState()
, который мы можем использовать для изменения текущего урла. Казалось бы, при чем тут state
, мы же просто добавляем в историю новую запись.Однако в сигнатуре этого метода три параметра, и урл - последний из них и необязательный. Первым идет
state object
- объект состояния, в который можно записать все, что угодно. Таким образом, в истории хранится именно состояние, какие-то данные, а урл может и не меняться.Получить текущее состояние можно из
window.history.state
.React Router позволяет удобно пользоваться этой фишкой прямо из объекта
location
, таким образом состояние привязывается к местоположению, а не к истории.Чтобы установить state для location, можно использовать проп
state
компонента Link
. В него можно установить любые данные. Также state можно передать в функцию navigate
, полученную из хука useNavigate
.Чтобы получить текущий state, нужно использовать хук
useLocation
. Он возвращает объект location
с полем location.state
.Кейсы для использования:
- сохранение предыдущей локации для последующего перенаправления
- отправка данных (обычно урезанных, самых необходимых) для быстрого отображения на новой локации, пока основные данные загружаются
#роутинг #документация #паттерны
Telegram
React Junior
React Router. Аутентификация
Пример из документации: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/auth?file=src%2FApp.tsx
Структура приложения
Есть открытая страница PublicPage, доступная по пути /. И есть закрытая страница ProtectedPage…
Пример из документации: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/auth?file=src%2FApp.tsx
Структура приложения
Есть открытая страница PublicPage, доступная по пути /. И есть закрытая страница ProtectedPage…
React Router. Модальное окно
Пример реализации модального окна с помощью роутера: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/modal?file=src/App.tsx
В приложении есть два контейнера
Когда модальное окно открывается, текущая активная страница записывается в
в Location.state и служит "фоновым роутом".
#роутинг #документация #примерыкода
Пример реализации модального окна с помощью роутера: https://stackblitz.com/github/remix-run/react-router/tree/main/examples/modal?file=src/App.tsx
В приложении есть два контейнера
Routes
, так что модальное окно может отображаться одновременно с основной страницей. При этом одна ветка роутов использует текущее значение location
, а для другой оно задается вручную с помощью пропа location
.Когда модальное окно открывается, текущая активная страница записывается в
в Location.state и служит "фоновым роутом".
#роутинг #документация #примерыкода
StackBlitz
React-router Modal Example - StackBlitz
Run official live example code for React-router Modal, created by Remix Run on StackBlitz
Программное создание конфига роутинга
https://stackblitz.com/github/remix-run/react-router/tree/main/examples/route-objects?file=src/App.tsx
Пример создания дерева роутов с помощью хука
#роутинг #документация #примерыкода
https://stackblitz.com/github/remix-run/react-router/tree/main/examples/route-objects?file=src/App.tsx
Пример создания дерева роутов с помощью хука
useRoutes
как альтернатива использованию элементов Routes
и Route
.#роутинг #документация #примерыкода
Stackblitz
React-router Route Objects Example - StackBlitz
Run official live example code for React-router Route Objects, created by Remix Run on StackBlitz
Повторный рендеринг и мемоизация в React
Статья (рус.): https://nuancesprog.ru/p/14850/
Вспоминаем о принципах рендеринга в React и способах его оптимизировать.
Повторный рендеринг обычно происходит из-за изменения пропсов или состояния компонента, при этом ререндерятся и все дочерние компоненты изменившегося родителя.
useRef
Обычно для изменяющихся значений используют
Подробнее про useRef
memo
Так как компоненты React - это обычные функции, их можно мемоизировать (сохранять результат работы для каждого набора входных параметров - пропсов). Для мемоизации используется HOC
Подробнее про React.memo
useCallback
Если в компоненте создается какая-либо функция, например, коллбэк для обработки события, она будет создаваться заново при каждом рендере.
Если вы используете мемоизированный компонент, но передаете в него такую изменяющуюся функцию, то все труды по мемоизации пройдут напрасно.
Такие функции следует оборачивать в хук
Подробнее про useCallback
useMemo
Хук
В отличие от
Подробнее про useMemo
Ленивая инициализация useState
В хук
Может быть полезно, если вычисление начального значения требует больших затрат.
Подробнее про ленивую инициализацию
#ссылки #оптимизация #хуки #hoc #паттерны
Статья (рус.): https://nuancesprog.ru/p/14850/
Вспоминаем о принципах рендеринга в React и способах его оптимизировать.
Повторный рендеринг обычно происходит из-за изменения пропсов или состояния компонента, при этом ререндерятся и все дочерние компоненты изменившегося родителя.
useRef
Обычно для изменяющихся значений используют
useState
. Но это хорошо только в том случае, если это значение влияет на вывод компонента. В ином случае лучше применять useRef
, тогда при изменениях не будет лишнего перерендера.Подробнее про useRef
memo
Так как компоненты React - это обычные функции, их можно мемоизировать (сохранять результат работы для каждого набора входных параметров - пропсов). Для мемоизации используется HOC
React.memo()
.Подробнее про React.memo
useCallback
Если в компоненте создается какая-либо функция, например, коллбэк для обработки события, она будет создаваться заново при каждом рендере.
Если вы используете мемоизированный компонент, но передаете в него такую изменяющуюся функцию, то все труды по мемоизации пройдут напрасно.
Такие функции следует оборачивать в хук
useCallback
, чтобы ссылка на функцию не изменялась.Подробнее про useCallback
useMemo
Хук
useMemo
предназначен для мемоизации отдельных функций внутри компонентов. Особенно полезен для "сложных" функций, которые тратят много ресурсов при выполнении.В отличие от
useCallback
, useMemo
сохраняет не саму функцию, а результат ее выполнения.Подробнее про useMemo
Ленивая инициализация useState
В хук
useState
можно передать функцию вместо начального состояния. Эта функция будет вызвана только один раз при первом рендеринге компонента.Может быть полезно, если вычисление начального значения требует больших затрат.
Подробнее про ленивую инициализацию
#ссылки #оптимизация #хуки #hoc #паттерны
NOP::Nuances of programming
Повторный рендеринг и мемоизация в React
Разработчики React прикладывают максимум усилий, чтобы увеличить производительность своего продукта. Сегодня мы рассмотрим основные инструменты оптимизации эффективности этой библиотеки.
👍2
Управление состоянием
Разобравшись более-менее с маршрутизацией (значимых альтернатив React Router вроде не нашлось), переходим к новой большой (очень большой) теме: управление глобальным состоянием приложения.
В ее рамках планирую:
- освежить в памяти хук
- взглянуть на Redux (должно быть что-то очень похожее на предыдущую комбинацию)
- попробовать Redux Toolkit (набор инструментов для работы с Redux)
- разобрать альтернативные решения - Recoil, MobX и, может, что-то еще
#состояние #управлениесостоянием
Разобравшись более-менее с маршрутизацией (значимых альтернатив React Router вроде не нашлось), переходим к новой большой (очень большой) теме: управление глобальным состоянием приложения.
В ее рамках планирую:
- освежить в памяти хук
useReducer
и совместить его с хуком useContext
для создания глобального состояния- взглянуть на Redux (должно быть что-то очень похожее на предыдущую комбинацию)
- попробовать Redux Toolkit (набор инструментов для работы с Redux)
- разобрать альтернативные решения - Recoil, MobX и, может, что-то еще
#состояние #управлениесостоянием
👍3
Что такое стейт-менеджер
Заметка (рус.): https://gist.github.com/nodkz/41a5ee356581503033bd05104f5048bf
Интересный взгляд на управление состоянием с историческими параллелями и выделением самого главного.
Главный вывод
Стейт-Менеджер = Переменная + Функция (для измнения переменной) + паттерн Observable (чтобы подписаться на изменение переменной)
#управлениесостоянием #ссылки
Заметка (рус.): https://gist.github.com/nodkz/41a5ee356581503033bd05104f5048bf
Интересный взгляд на управление состоянием с историческими параллелями и выделением самого главного.
Главный вывод
Стейт-Менеджер = Переменная + Функция (для измнения переменной) + паттерн Observable (чтобы подписаться на изменение переменной)
#управлениесостоянием #ссылки
Gist
Что такое Стейт Менеджер для вас?
Что такое Стейт Менеджер для вас? GitHub Gist: instantly share code, notes, and snippets.
👍1
Почему React Context - это не инструмент для "управления состоянием" (и почему он не может заменить Redux)
Большая статья с подробным сравнением React Context и Redux (англ.): https://blog.isquaredsoftware.com/2021/01/context-redux-differences/
Основная идея заключается в том, что контекст сам по себе не имеет никакого отношения к управлению состоянием, а является только механизмом доставки данных без утомительного проброса пропсов. В некотором смысле это паттерн Внедрение зависимостей (Dependency Injection).
Контекст в комбинации с хуком
Redux же - это полноценный менеджер состояния, специально созданный для этой задачи. Он позволяет работать с большими и сложными состояниями, хорошо масштабируется и дает массу дополнительных плюшек.
React-Redux под капотом также использует контекст, но пробрасывает не сами данные, а собственно объект хранилища. То есть использует контекст для внедрения зависимостей.
Статья написана очень подробно и понятно, рекомендую 🙂
#ссылки #управлениесостоянием #redux #контекст
Большая статья с подробным сравнением React Context и Redux (англ.): https://blog.isquaredsoftware.com/2021/01/context-redux-differences/
Основная идея заключается в том, что контекст сам по себе не имеет никакого отношения к управлению состоянием, а является только механизмом доставки данных без утомительного проброса пропсов. В некотором смысле это паттерн Внедрение зависимостей (Dependency Injection).
Контекст в комбинации с хуком
useReducer
- это уже что-то более похожее на state managment, но совсем на минималках. Тут уже можно работать с более-менее сложным состоянием. Это может быть хорошим решением для небольших проектов. Основная проблема - невозможность разделения данных. Если компонент подписывается на изменением состояния, то он будет перерендерен при любом его изменении, даже если изменилась часть, которая этот конкретный компонент не интересует. Конечно, можно создавать отдельные контексты для разных данных, но тут потенциал масштабирования очень маленький.Redux же - это полноценный менеджер состояния, специально созданный для этой задачи. Он позволяет работать с большими и сложными состояниями, хорошо масштабируется и дает массу дополнительных плюшек.
React-Redux под капотом также использует контекст, но пробрасывает не сами данные, а собственно объект хранилища. То есть использует контекст для внедрения зависимостей.
Статья написана очень подробно и понятно, рекомендую 🙂
#ссылки #управлениесостоянием #redux #контекст
Mark's Dev Blog
Blogged Answers: Why React Context is Not a "State Management" Tool (and Why It Doesn't Replace Redux)
Definitive answers and clarification on the purpose and use cases for Context and Redux
Вспоминаем useReducer
Хук
У нас есть значение и функция, которой нужно передать новое значение. Мы сразу определяем, что должно лежать в
Но что если логика расчета нового
Для этого у нас есть хук
Тут не нужно сразу рассчитывать новое значение, достаточно лишь указать, какое действие произошло. Мы переходим на новую, более декларативную, концепцию - экшены.
Представим простейшую ситуацию: у нас есть некий счетчик. При нажатии на кнопку +1 мы хотим увеличить его значение на единицу.
С
С
Это действие передается в редьсер, который уже вычисляет новое значие
В общем, ничего сложного, просто небольшой сдвиг мировоззрения. Две новые концепции - инкапсуляция логики изменения состояния в функции редьюсере и экшены - типа команды для изменения состояния.
#хуки #управлениесостоянием #состояние
Хук
useState
работает очень просто:
const [value, setValue] = useState()
У нас есть значение и функция, которой нужно передать новое значение. Мы сразу определяем, что должно лежать в
value
, и передаем это в setValue
.Но что если логика расчета нового
value
сложнее, чем прибавить единицу к предыдущему значению? Если есть несколько причин для изменения value
и хотелось бы контролировать их все в одном месте, иначе отлаживать будет невозможно?Для этого у нас есть хук
useReducer
, который по сути является более продвинутым useState
. Говорили про него здесь. Он позволяет инкапсулировать всю логику изменения состояния в одной функции - редьюсере.
const [value, dispatch] = useReducer(reducer, initialValue)
Тут не нужно сразу рассчитывать новое значение, достаточно лишь указать, какое действие произошло. Мы переходим на новую, более декларативную, концепцию - экшены.
Представим простейшую ситуацию: у нас есть некий счетчик. При нажатии на кнопку +1 мы хотим увеличить его значение на единицу.
С
useState
это выглядит так:
setValue(function(currentValue) {
return currentValue + 1;
})
С
useReducer
мы передаем не значение, а действие:
dispatch({ type: 'increment' })
Это действие передается в редьсер, который уже вычисляет новое значие
value
, исходя из типа экшена.В общем, ничего сложного, просто небольшой сдвиг мировоззрения. Две новые концепции - инкапсуляция логики изменения состояния в функции редьюсере и экшены - типа команды для изменения состояния.
#хуки #управлениесостоянием #состояние
Telegram
React Junior
useReducer
Альтернатива useState для более сложной логики состояния.
Сигнатура: const [state, dispatch] = useReducer(reducer, initialArg, init);
- reducer - функция с сигнатурой (state, action) => newState, которая должна вернуть актуальное состояние…
Альтернатива useState для более сложной логики состояния.
Сигнатура: const [state, dispatch] = useReducer(reducer, initialArg, init);
- reducer - функция с сигнатурой (state, action) => newState, которая должна вернуть актуальное состояние…
Очень простой пример использования
https://codesandbox.io/s/usereducer-react-junior-5x89x8?file=/src/App.js
Редьюсер и начальное состояние вынесены в отдельный файл state.js. Функция-редьюсер получает экшен, смотрит на его тип и производит все необходимые изменения, возвращает обновленное состояние.
Экшены отправляются с помощью функции
У нас есть четыре типа экшенов, которые понимает редьюсер: increment, decrement, add (с полезной нагрузкой, параметром, который определяет, сколько именно нужно прибавить к счетчику) и reset.
#примерыкода #хуки #состояние #управлениесостоянием
useReducer
https://codesandbox.io/s/usereducer-react-junior-5x89x8?file=/src/App.js
Редьюсер и начальное состояние вынесены в отдельный файл state.js. Функция-редьюсер получает экшен, смотрит на его тип и производит все необходимые изменения, возвращает обновленное состояние.
Экшены отправляются с помощью функции
dispatch
, которую возвращает хук.У нас есть четыре типа экшенов, которые понимает редьюсер: increment, decrement, add (с полезной нагрузкой, параметром, который определяет, сколько именно нужно прибавить к счетчику) и reset.
#примерыкода #хуки #состояние #управлениесостоянием
CodeSandbox
useReducer. React Junior - CodeSandbox
useReducer. React Junior by furrycat.web using react, react-dom, react-scripts
useReducer + useContext
Реализуем управление состоянием с помощью только хуков React (комбинация useReducer + useContext), без использования сторонних библиотек.
https://codesandbox.io/s/usereducer-usecontext-react-junior-um0bsr?file=/src/App.js
*Пример условный, упрощенный и неоптимизированный, только для демонстрации работы с состоянием
Мы имеем тут какой-то личный финансовый кабинет. У пользователя есть баланс средств, баланс бонусов (10 бонусов начисляется, если пользователь вносит больше 1000), а также возможность пополнить баланс или снять деньги.
Состояние
Все состояние хранится в одном месте (файл state.js). Там же определен редьюсер, который понимает экшены двух типов
Контекст
Контекст используется, чтобы передавать состояние приложения в любой заинтересованный компонент без проброса пропсов. Все кейсы использования контекста (компонент-провайдер и хук для доступа к контексту) собраны в файле depositeContext.js.
Схема работы
1. В корневом компоненте
2. Создаем отдельный контекст с помощью хука
3. В заинтересованных компонентах получаем доступ к контексту (и функции
#хуки #управлениесостоянием #состояние #примерыкода
Реализуем управление состоянием с помощью только хуков React (комбинация useReducer + useContext), без использования сторонних библиотек.
https://codesandbox.io/s/usereducer-usecontext-react-junior-um0bsr?file=/src/App.js
*Пример условный, упрощенный и неоптимизированный, только для демонстрации работы с состоянием
Мы имеем тут какой-то личный финансовый кабинет. У пользователя есть баланс средств, баланс бонусов (10 бонусов начисляется, если пользователь вносит больше 1000), а также возможность пополнить баланс или снять деньги.
Состояние
Все состояние хранится в одном месте (файл state.js). Там же определен редьюсер, который понимает экшены двух типов
put
(пополнение) и withdraw
(снятие). Редьюсер меняет баланс, следит за начислением бонусов, сохраняет историю операций. Кроме того, в состояние добавлено поле error
- какая-либо ошибка при выполнении операций.Контекст
Контекст используется, чтобы передавать состояние приложения в любой заинтересованный компонент без проброса пропсов. Все кейсы использования контекста (компонент-провайдер и хук для доступа к контексту) собраны в файле depositeContext.js.
Схема работы
1. В корневом компоненте
App
создаем состояние с помощью хука useReducer
, получаем функцию dispatch
для управления состоянием.2. Создаем отдельный контекст с помощью хука
useContext
, оборачиваем все приложение в провайдер этого контекста. В контекст добавляем и само состояние, и функцию dispatch
.3. В заинтересованных компонентах получаем доступ к контексту (и функции
dispatch
) с помощью кастомного хука useDepositeContext
(под капотом обычный useContext
). #хуки #управлениесостоянием #состояние #примерыкода
Telegram
React Junior
Вспоминаем useReducer
Хук useState работает очень просто:
const [value, setValue] = useState()
У нас есть значение и функция, которой нужно передать новое значение. Мы сразу определяем, что должно лежать в value, и передаем это в setValue.
Но что если…
Хук useState работает очень просто:
const [value, setValue] = useState()
У нас есть значение и функция, которой нужно передать новое значение. Мы сразу определяем, что должно лежать в value, и передаем это в setValue.
Но что если…
Задача: при внесении большой суммы на счет (больше тысячи) нужно добавлять клиенту бонусы. Где должна находиться эта логика (проверка суммы)?
Anonymous Poll
65%
В редьюсере
20%
В компоненте
15%
Где-то еще (где?)
useReducer + useContext + асинхронное обновление состояния
Еще один небольшой проект с глобальным состоянием на хуках: https://codesandbox.io/s/usereducer-usecontext-async-react-junior-i13xix?file=/src/App.js
Это приложение для поиска аниме с фильтрами. Для поиска аниме используется бесплатное апи jikan.moe. Для отправки запросов - библиотека axios.
В состоянии помимо списка подходящих аниме хранится также флаг
При нажатии на кнопку Search диспатчится событие
⁉️ Сама логика запроса списка находится в компоненте
#управлениесостоянием #хуки #примерыкода
Еще один небольшой проект с глобальным состоянием на хуках: https://codesandbox.io/s/usereducer-usecontext-async-react-junior-i13xix?file=/src/App.js
Это приложение для поиска аниме с фильтрами. Для поиска аниме используется бесплатное апи jikan.moe. Для отправки запросов - библиотека axios.
В состоянии помимо списка подходящих аниме хранится также флаг
loading
, обозначающий процесс загрузки данных. При нажатии на кнопку Search диспатчится событие
START_LOADING
, а при получении данных событие UPDATE
. ⁉️ Сама логика запроса списка находится в компоненте
App
, показалось неправильным размещать ее ниже по дереву, но это не точно, конечно. Вместо dispatch
вниз по контексту уходит готовый метод обновления списка updateList
. Вообще пока не очень понятно, как правильно работать с асинхронным обновлением состояния, как технически реализовывать и где ему место. Ведь в редьюсер его не положишь.#управлениесостоянием #хуки #примерыкода
CodeSandbox
useReducer + useContext + async. React Junior - CodeSandbox
useReducer + useContext + async. React Junior by furrycat.web using axios, react, react-dom, react-scripts
Глубокое погружение в код 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