Redux Essentials 3. Страница статьи
Добавляем возможность просмотреть отдельную статью.
https://codesandbox.io/s/redux-essentials-single-post-page-react-junior-3dziwq?file=/src/App.js
Для этого понадобится новый роут вида
Роут будет динамический (с параметром -
Помним, что селектор должен лежать рядом со слайсом, так как он знает, как получать данные из хранилища. В руководстве селекторы объявляются в компонентах.
Если статья с указанным идентификатором не нашлась, выводим сообщение.
Наконец, добавляем ссылки на посты в компоненте
#redux #управлениесостоянием #документация #примерыкода
Добавляем возможность просмотреть отдельную статью.
https://codesandbox.io/s/redux-essentials-single-post-page-react-junior-3dziwq?file=/src/App.js
Для этого понадобится новый роут вида
/posts/123
и компонент SinglePostPage
(лежит в папке features/posts).Роут будет динамический (с параметром -
/posts/:id
), в компонент нужно получить сначала значение этого параметра, чтобы узнать, с какой статьей мы имеем дело (хук useParams
из react-router). А затем - получить данные статьи из хранилища с помощью селектора (getPostData
).Помним, что селектор должен лежать рядом со слайсом, так как он знает, как получать данные из хранилища. В руководстве селекторы объявляются в компонентах.
Если статья с указанным идентификатором не нашлась, выводим сообщение.
Наконец, добавляем ссылки на посты в компоненте
PostsList
.#redux #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. Single post page. React Junior - CodeSandbox
Redux Essentials. Single post page. React Junior by furrycat.web using @reduxjs/toolkit, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍3
Redux Essentials 4. Редактирование статьи
https://codesandbox.io/s/redux-essentials-edit-post-react-junior-hbfrh5?file=/src/App.js
Чтобы иметь возможность редактировать статью, нам понадобится:
- новый роут
1) В компоненте получаем id поста из урла с помощью
2) Затем получаем данные поста с помощью селектора
3) Все состояние формы хранится локально.
4) При отправке формы диспатчим экшен с помощью креатора
5) Переходим на роут поста, чтобы увидеть изменения (хук
Так как формы создания и редактирования очень похожи (фактически, это одна и та же форма), появилось большое искушение вынести ее в отдельный компонент - /components/PostForm.js. Он немного избыточен, включает в себя помимо формы еще и текст заголовка и общие стили контейнера, но почему бы и нет.
Что касается экшенов
#redux #управлениесостоянием #документация #примерыкода
https://codesandbox.io/s/redux-essentials-edit-post-react-junior-hbfrh5?file=/src/App.js
Чтобы иметь возможность редактировать статью, нам понадобится:
- новый роут
/editPost/:id
- компонент формы EditPostForm
- новый экшен postUpdated
, чтобы внести изменения в данные1) В компоненте получаем id поста из урла с помощью
useParams
. 2) Затем получаем данные поста с помощью селектора
getPostData
и подставляем их в форму. 3) Все состояние формы хранится локально.
4) При отправке формы диспатчим экшен с помощью креатора
postUpdated
, передавая ему всю необходимую информацию.5) Переходим на роут поста, чтобы увидеть изменения (хук
useNavigate
).Так как формы создания и редактирования очень похожи (фактически, это одна и та же форма), появилось большое искушение вынести ее в отдельный компонент - /components/PostForm.js. Он немного избыточен, включает в себя помимо формы еще и текст заголовка и общие стили контейнера, но почему бы и нет.
Что касается экшенов
postAdded
, postUpdated
. Тут как будто напрашивается нормализованное состояние и createEntityAdapter. Посмотрим, что будет дальше.#redux #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. Edit post. React Junior - CodeSandbox
Redux Essentials. Edit post. React Junior by furrycat.web using @reduxjs/toolkit, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍4
Redux Essentials 5. Авторы постов
Следующий шаг - добавляем в приложение пользователей, ведь статьи не сами собой пишутся.
И тут становится понятно, что решение вынести форму создания/редактирования статьи в отдельный компонент было слишком поспешным. В форму создания нужно будет внести изменения, поэтому теперь это два разных компонента, как и было задумано в руководстве.
https://codesandbox.io/s/redux-essentials-users-slice-react-junior-52ltvw?file=/src/App.js
Что делаем?
1. Добавляем новую фичу
2. В форму создания поста добавлям селект для выбора автора (это сделано для простоты и наглядности, в реальном приложении обычно есть механизмы для определения активного пользователя). Список пользователей получаем с помощью
3. Немного изменяем экшен
4. Создаем отдельный компонент
5. Наконец, подключаем этот компонент в каждый пост в ленте
#redux #управлениесостоянием #документация #примерыкода
Следующий шаг - добавляем в приложение пользователей, ведь статьи не сами собой пишутся.
И тут становится понятно, что решение вынести форму создания/редактирования статьи в отдельный компонент было слишком поспешным. В форму создания нужно будет внести изменения, поэтому теперь это два разных компонента, как и было задумано в руководстве.
https://codesandbox.io/s/redux-essentials-users-slice-react-junior-52ltvw?file=/src/App.js
Что делаем?
1. Добавляем новую фичу
users
и новый слайс usersSlice
. Здесь хранится простой список пользователей, даже никаких экшенов нет (пока по крайней мере). Подключаем слайд к хранилищу в файле store.js
. Сразу создаем два селектора - для получения всего списка и для получения отдельного пользователя по идентификатору.2. В форму создания поста добавлям селект для выбора автора (это сделано для простоты и наглядности, в реальном приложении обычно есть механизмы для определения активного пользователя). Список пользователей получаем с помощью
useSelector
. 3. Немного изменяем экшен
posts/postAdded
. Теперь он получает три отдельных параметра вместо одного объекта, поэтому оформляем его в виде массива с полями reducer
и prepare
.4. Создаем отдельный компонент
/posts/PostAuthor.js
, который будет получать id пользователя и выводить его имя.5. Наконец, подключаем этот компонент в каждый пост в ленте
PostsList
и в компонент SinglePostPage
.#redux #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. Users slice. React Junior - CodeSandbox
Redux Essentials. Users slice. React Junior by furrycat.web using @reduxjs/toolkit, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍3
Redux Essentials 6. Дата поста
Следующий шаг очень простой и мало связанный, на самом деле, с Redux - добавляем даты создания статей.
https://codesandbox.io/s/redux-essentials-dates-react-junior-y8f6x8?file=/src/App.js
1. Вносим изменения в слайс: добавляем постам новое поле
Важно: Так как в хранилище должны находиться только сериализуемые данные, вместо даты записываем туда строковый
2. Создаем отдельный компонент
3. Выводим дату в списке статей и на странице отдельного поста.
4. В списке дополнительно сортируем статьи по дате, выводя более свежие первыми. Теперь можно добавить новую статью в форме создания, и она окажется первой в списке.
#redux #управлениесостоянием #документация #примерыкода
Следующий шаг очень простой и мало связанный, на самом деле, с Redux - добавляем даты создания статей.
https://codesandbox.io/s/redux-essentials-dates-react-junior-y8f6x8?file=/src/App.js
1. Вносим изменения в слайс: добавляем постам новое поле
date
, устанавливаем текущую дату при создании поста. На прошлом шаге мы разделели редьюсер postAdded
на reducer
и prepare
. Вот как раз в prepare
и добавляется этот новый "подготовительный" функционал.Важно: Так как в хранилище должны находиться только сериализуемые данные, вместо даты записываем туда строковый
timestamp
.2. Создаем отдельный компонент
TimeAgo
для вывода даты (в формате 5 минут назад). Для форматирования используется библиотека date-fns. 3. Выводим дату в списке статей и на странице отдельного поста.
4. В списке дополнительно сортируем статьи по дате, выводя более свежие первыми. Теперь можно добавить новую статью в форме создания, и она окажется первой в списке.
#redux #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. Dates. React Junior - CodeSandbox
Redux Essentials. Dates. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍1
Redux Essentials 7. Реакции
Добавляем реакции к статьям.
https://codesandbox.io/s/redux-essentials-reactions-react-junior-1p1k32?file=/src/App.js
1. У каждой статьи появляется поле
2. Добавляется новый экшен
3. Добавляется компонент
Механизм реакций, конечно, работает неправильно - сейчас можно ставить сколько угодно лайков, тогда как в реальных приложениях обычно только по одному. Для этого нужно дополнительно сохранять информацию о том, какой юзер что лайкнул. Возможно, это будет реализовано позже.
#redux #управлениесостоянием #документация #примерыкода
Добавляем реакции к статьям.
https://codesandbox.io/s/redux-essentials-reactions-react-junior-1p1k32?file=/src/App.js
1. У каждой статьи появляется поле
reactions
с набором доступных реакций и счетчиком для каждой реакции.2. Добавляется новый экшен
reactionAdded
, который увеличивает счетчик выбранного смайлика.3. Добавляется компонент
ReactionButtons
- набор кнопок с разными реакциями.Механизм реакций, конечно, работает неправильно - сейчас можно ставить сколько угодно лайков, тогда как в реальных приложениях обычно только по одному. Для этого нужно дополнительно сохранять информацию о том, какой юзер что лайкнул. Возможно, это будет реализовано позже.
#redux #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. Reactions. React Junior - CodeSandbox
Redux Essentials. Reactions. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍2
Forwarded from Cat in Web
Легковесные альтернативы Redux
Статья (англ.): https://blog.openreplay.com/lightweight-alternatives-to-redux
Автор статьи рассказывает, какие инструменты можно использовать для управления глобальным состоянием приложения вместо Redux.
1. Хуки React
Простейший вариант - использовать встроенные хуки. С помощью
2. Zustand
Zustand использует те же flux-принципы, что и Redux. Мы создаем хранилище с помощью функции
3. Jotai
Разработан той же командой, что и Zustand, но использует другой подход - атомарный (atomic). Каждая часть данных оформляется в виде атома с помощью функции
4. Valtio
Подход Valtio базируется на использовании прокси. Мы передаем объект в функцию
В статье есть примеры кода для всех этих решений, можно сформировать общее впечатление и заинтересоваться чем-нибудь.
#redux #react #statemanagement #library
Статья (англ.): https://blog.openreplay.com/lightweight-alternatives-to-redux
Автор статьи рассказывает, какие инструменты можно использовать для управления глобальным состоянием приложения вместо Redux.
1. Хуки React
Простейший вариант - использовать встроенные хуки. С помощью
useReducer
мы выносим состояние приложения в отдельный объект и можем удобно им управлять, а с помощью контекста доставляем этот объект до всех заинтересованных компонентов. Пример.2. Zustand
Zustand использует те же flux-принципы, что и Redux. Мы создаем хранилище с помощью функции
create
и получаем из нее хук useStore
, который можно использовать в компонентах. 3. Jotai
Разработан той же командой, что и Zustand, но использует другой подход - атомарный (atomic). Каждая часть данных оформляется в виде атома с помощью функции
atom
. Для работы с атомами есть хук useAtom
, который работает так же, как useState
. 4. Valtio
Подход Valtio базируется на использовании прокси. Мы передаем объект в функцию
proxy
и дальше можем его мутировать - прокси отслеживает все изменения.В статье есть примеры кода для всех этих решений, можно сформировать общее впечатление и заинтересоваться чем-нибудь.
#redux #react #statemanagement #library
Openreplay
Lightweight Alternatives to Redux
Forget about Redux for a minute and think aboutside the box
👍2
Forwarded from Cat in Web
React World
Развлекалочка на React: https://sfatihk.github.io/react-world/
Скроль страницу и совершай небольшое путешествие с героями любимых фильмов.
А потом можно залезть в исходники и посмотреть, как все это работает: https://github.com/sfatihk/react-world
#react
Развлекалочка на React: https://sfatihk.github.io/react-world/
Скроль страницу и совершай небольшое путешествие с героями любимых фильмов.
А потом можно залезть в исходники и посмотреть, как все это работает: https://github.com/sfatihk/react-world
#react
👍2
Redux Essentials 8. Запрос данных
Теперь сделаем наше приложение более реалистичным - установим связь с "сервером". В настоящих приложениях данных приходят из базы, а не хранятся на клиенте, поэтому нам нужно их получать и отправлять.
https://codesandbox.io/s/redux-essentials-fetch-posts-react-junior-kx3out?file=/src/App.js
В руководстве используется специальный фейковый REST API с сервером и клиентом, но я не буду так заморачиваться, сделаю простую имитацию с
Thunks
Хранилище работает синхронно, в редьюсерах не должно быть асинхронной логики. Поэтому мы выносим ее в thunks (санки).
Санки - это функции, которые имеют доступ к хранилищу (через аргументы). Они могут выполнять любые асинхронные действия и в нужный момент диспатчить что-нибудь в хранилище.
Мы работаем с санками как с экшенами, передаем их в метод
createAsyncThunk
Для создания санков используем метод createAsyncThunk. Передаем ему префикс для экшенов и функцию с логикой асинхронного запроса, которая должна возвращать промис. Под капотом
Итак, thunk creator у нас есть и экшены, связанные с ним, тоже. Но хранилище пока ничего не знает об этих экшенах и не умеет их обрабатывать. Добавляем редьюсеры для них с помощью метода
Состояние и отображение
Немного меняем состояние, теперь в нем есть поле
Список
Кроме того, в этом же компоненте с помощью селектора извлекаем текущий статус запроса. Если данные еще грузятся, выводим лоадер, чтобы пользователь знал, что происходит.
#redux #управлениесостоянием #документация #примерыкода
Теперь сделаем наше приложение более реалистичным - установим связь с "сервером". В настоящих приложениях данных приходят из базы, а не хранятся на клиенте, поэтому нам нужно их получать и отправлять.
https://codesandbox.io/s/redux-essentials-fetch-posts-react-junior-kx3out?file=/src/App.js
В руководстве используется специальный фейковый REST API с сервером и клиентом, но я не буду так заморачиваться, сделаю простую имитацию с
setTimeout
.Thunks
Хранилище работает синхронно, в редьюсерах не должно быть асинхронной логики. Поэтому мы выносим ее в thunks (санки).
Санки - это функции, которые имеют доступ к хранилищу (через аргументы). Они могут выполнять любые асинхронные действия и в нужный момент диспатчить что-нибудь в хранилище.
Мы работаем с санками как с экшенами, передаем их в метод
dispatch
, а чтобы все правильно обрабатывалось, нужно использовать миддлвар redux-thunk. createAsyncThunk
Для создания санков используем метод createAsyncThunk. Передаем ему префикс для экшенов и функцию с логикой асинхронного запроса, которая должна возвращать промис. Под капотом
createAsyncThunk
диспатчит экшен перед началом выполнения и сразу после выполнения наше функции (может быть удачный или ошибочный).Итак, thunk creator у нас есть и экшены, связанные с ним, тоже. Но хранилище пока ничего не знает об этих экшенах и не умеет их обрабатывать. Добавляем редьюсеры для них с помощью метода
extraReducers
. extraReducers
это функция, которая в качестве аргумента получает builder
. Вот в этот билдер и нужно добавить обработчики для новых экшенов (метод builder.addCase
).Состояние и отображение
Немного меняем состояние, теперь в нем есть поле
items
для хранения списка постов, а также поля status
и error
для хранения состояния запроса. Вносим изменения в селекторы, так как путь к данным изменился. Добавляем также новый селектор getStatus
.Список
items
изначально пустой, чтобы его заполнить, нужно запросить данные "с сервера". Делаем это в компоненте PostsList
- внутри хука useEffect.Кроме того, в этом же компоненте с помощью селектора извлекаем текущий статус запроса. Если данные еще грузятся, выводим лоадер, чтобы пользователь знал, что происходит.
#redux #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. Fetch posts. React Junior - CodeSandbox
Redux Essentials. Fetch posts. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍1
Хорошие практики Redux
На базе предыдущего шага:
1. Инкапсуляция логики извлечения данных внутри селекторов. Структура хранилища изменилась, и если бы не было селекторов, пришлось бы вносить изменения во все компоненты, которые получают данных из хранилища.
2. Состояние запроса хранится в виде строки из перечисления (enum).
#redux #управлениесостоянием #паттерны
На базе предыдущего шага:
1. Инкапсуляция логики извлечения данных внутри селекторов. Структура хранилища изменилась, и если бы не было селекторов, пришлось бы вносить изменения во все компоненты, которые получают данных из хранилища.
2. Состояние запроса хранится в виде строки из перечисления (enum).
#redux #управлениесостоянием #паттерны
Telegram
React Junior
Статус асинхронного запроса
В документации Redux описан хороший паттерн работы с асинхронными запросами. Он не относится непосредственно к Redux, применять его можно где угодно.
Очень часто для отслеживания состояния запроса используют флаги типа isLoading…
В документации Redux описан хороший паттерн работы с асинхронными запросами. Он не относится непосредственно к Redux, применять его можно где угодно.
Очень часто для отслеживания состояния запроса используют флаги типа isLoading…
👍1
Еще раз про createAsyncThunk
Это функция для создания thunk creators. Используем, если нужны экшены начала и конца запроса.
❎ Без
Это функция для создания thunk creators. Используем, если нужны экшены начала и конца запроса.
❎ Без
createAsyncThunk
:// action creators✅ С
const getFetchPostsPending = function() {
type: 'posts/fetchPosts/pending'
};
const getFetchPostsFulfilled = function(posts) {
type: 'posts/fetchPosts/fulfilled',
payload: posts
};
const getFetchPostsRejected = function(error) {
type: 'posts/fetchPosts/rejected',
error
};
// thunk creator
const fetchPosts = function(params) {
return async function (dispatch) {
dispatch(getFetchPostsPending());
try {
const posts = await fakeApi.getPosts(params);
dispatch(getFetchPostsFulfilled(posts))
} catch (err) {
dispatch(getFetchPostsRejected(err.toString()))
}
}
}
// обработка
const postsReducer = function(state, action) {
switch(action.type) {
case 'posts/fetchPosts/pending':
// ...
case 'posts/fetchPosts/fulfilled':
// ...
case 'posts/fetchPosts/rejected':
// ...
}
}
createAsyncThunk
:// thunk creator#redux #управлениесостоянием #примерыкода
export const fetchPosts = createAsyncThunk("posts/fetchPosts", async function() {
const response = await fakeApi.getPosts();
return response.data;
});
// обработка
const postsSlice = createSlice({
// ...
extraReducers(builder) {
builder
.addCase(fetchPosts.pending, function(state, action) { })
.addCase(fetchPosts.fulfilled, function(state, action) { })
.addCase(fetchPosts.rejected, function(state, action) { });
}
})
👍1
Builder
У него есть три метода:
-
-
-
#redux #управлениесостоянием #документация
builder
позволяет добавлять в хранилище дополнительные редьюсеры - для дополнительных экшенов, которые генерируются где-то вне createSlice
.У него есть три метода:
-
builder.addCase
- для конкретного типа экшена. Первым аргументом нужно передать либо action creator, либо строку с типом экшена.-
bulder.addMatcher
- первым аргументом принимает функцию-матчер. В эту функцию передаются все экшены, редьюсер срабатывает, если матчер вернет true
.-
builder.addDefaultCase
- принимает только редьюсер, который срабатывает, если не сработал ни один другой редьюсер. #redux #управлениесостоянием #документация
👍2
Redux Essentials 9. Запрос пользователей
По аналогии с запросом статей делаем запрос пользователей.
https://codesandbox.io/s/redux-essentials-fetch-users-react-junior-ipw0r8?file=/src/App.js
1. Пишем thunk creator с помощью
2. Добавляем редьюсер для экшена
3. Диспатчим новый санк в файле
#redux #управлениесостоянием #документация #примерыкода
По аналогии с запросом статей делаем запрос пользователей.
https://codesandbox.io/s/redux-essentials-fetch-users-react-junior-ipw0r8?file=/src/App.js
1. Пишем thunk creator с помощью
createAsyncThunk
. 2. Добавляем редьюсер для экшена
fetchUsers.fulfilled
.3. Диспатчим новый санк в файле
index.js
, там где импортируем объект хранилища.#redux #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. Fetch users. React Junior - CodeSandbox
Redux Essentials. Fetch users. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍1
Redux Essentials 10. Сохранение постов
Добавляем еще один thunk creator
https://codesandbox.io/s/redux-essentials-create-post-react-junior-cbfh4u?file=/src/App.js
Убираем редьюсер
Для загрузки постов мы добавили в слайс поле
Добавляем еще один thunk creator
addNewPost
(с помощью createAsyncThunk
), который будет выполнять запрос к фейковому серверу, отправлять данные из формы и получать обратно объект нового поста (с уникальным id). Создание id происходит на сервере, как это обычно и бывает в реальных приложениях.https://codesandbox.io/s/redux-essentials-create-post-react-junior-cbfh4u?file=/src/App.js
Убираем редьюсер
postAdded
и вместо него добавляем новый кейс в extraReducers
- для экшена addNewPost.fulfilled
.Для загрузки постов мы добавили в слайс поле
status
и отслеживали статус запроса, чтобы отображать лоадер. Здесь пойдем другим путем - будем отслеживать статус прямо в компоненте (подробнее - возвращение промиса из thunk). Пока идет запрос, заблокируем отправку формы.await dispatch(addNewPost({ title, content, user: userId })).unwrap()Обратите внимание на метод
unwrap()
у результата выполнения функции dispatch
. Его добавляет Redux Toolkit. Если промис завершился неудачно, этот метод выбросит ошибку, которую мы сможем поймать в try...catch
#redux #управлениесостоянием #документация #примерыкодаCodeSandbox
Redux Essentials. Create post. React Junior - CodeSandbox
Redux Essentials. Create post. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍1
Redux Essentials 11. Список авторов и страница автора
На следующем этапе добавляем страницу со списком пользователей и страницу отдельного пользователя со списком статей.
https://codesandbox.io/s/redux-essentials-users-list-user-page-react-junior-xmtqds?file=/src/App.js
Ничего нового:
1) Новый селектор
3) Новый компонент UserPage (использует хук
4) Новые роуты
5) Ссылка на страницу авторов в шапке сайта + ссылки на авторов в превью статей и на странице статьи
#redux #управлениесостоянием #документация #примерыкода
На следующем этапе добавляем страницу со списком пользователей и страницу отдельного пользователя со списком статей.
https://codesandbox.io/s/redux-essentials-users-list-user-page-react-junior-xmtqds?file=/src/App.js
Ничего нового:
1) Новый селектор
getUserPosts
в postsSlice
2) Новый компонент UsersList (использует селектор getUsers
)3) Новый компонент UserPage (использует хук
useParams
и селектор getUserPosts
)4) Новые роуты
/users
и /users/:userId
в App.js5) Ссылка на страницу авторов в шапке сайта + ссылки на авторов в превью статей и на странице статьи
#redux #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. Users list & User page. React Junior - CodeSandbox
Redux Essentials. Users list & User page. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
👍1
Forwarded from Cat in Web
React 18
Перевод оригинальной статьи на Хабре: https://habr.com/ru/post/659537/
Обзор новинок последнего релиза - а их немало.
Конкурентный рендеринг
Кардинально изменилась модель рендеринга, появилась конкурентность - нечто подкапотное, что позволяет подготавливать несколько версий интерфейса одновременно. Рендеринг теперь может прерываться, откладываться (раньше был синхронным). Благодаря этому основной поток не блокируется и приложение может реагировать на действия пользователя, даже если за кулисами рендерится что-то огромное.
Появилось несколько новых хуков для работы с новым функционалом, однако в перспективе команда React ожидает, что они будут использоваться в основном для интеграции библиотек с поддержкой конкурентности, а не напрямую. Например, библиотекой маршрутизации для перехода между страницами.
Автоматическое пакетирование
Или группировка нескольких обновлений в один рендеринг. Раньше пакетировались только обновления внутри обработчиков событий React, теперь пакетируются еще и обновления внутри промисов, таймеров, нативных обработчиков и пр.
Переходы (transitions)
Обновления теперь делятся на срочные (немедленная реакция на действие пользователя, например, ввод текста) и переходные (не срочные). Последние - это переход интерфейса из одного состояния в другое (например, появление списка результатов после применения фильтров).
Новая функция
Suspense
Расширились возможности React.Suspense. Раньше он только позволял лениво загружать код с помощью React.lazy и не поддерживался при серверном рендеринге. Теперь работает и на сервере тоже и хорошо сочетается с API переходов.
Новые API рендеринга
Новые методы для рендеринга -
Двойное монтирование компонентов
В строгом режиме в dev mode добавлена проверка на "устойчивость к многократному монтированию" - компоненты в первый раз монтируются, сразу размонтируются с сохранением состояния и монтируются снова. Это нужно для будущих улучшений.
Новые хуки
-
-
-
-
-
#react
Перевод оригинальной статьи на Хабре: https://habr.com/ru/post/659537/
Обзор новинок последнего релиза - а их немало.
Конкурентный рендеринг
Кардинально изменилась модель рендеринга, появилась конкурентность - нечто подкапотное, что позволяет подготавливать несколько версий интерфейса одновременно. Рендеринг теперь может прерываться, откладываться (раньше был синхронным). Благодаря этому основной поток не блокируется и приложение может реагировать на действия пользователя, даже если за кулисами рендерится что-то огромное.
Появилось несколько новых хуков для работы с новым функционалом, однако в перспективе команда React ожидает, что они будут использоваться в основном для интеграции библиотек с поддержкой конкурентности, а не напрямую. Например, библиотекой маршрутизации для перехода между страницами.
Автоматическое пакетирование
Или группировка нескольких обновлений в один рендеринг. Раньше пакетировались только обновления внутри обработчиков событий React, теперь пакетируются еще и обновления внутри промисов, таймеров, нативных обработчиков и пр.
Переходы (transitions)
Обновления теперь делятся на срочные (немедленная реакция на действие пользователя, например, ввод текста) и переходные (не срочные). Последние - это переход интерфейса из одного состояния в другое (например, появление списка результатов после применения фильтров).
Новая функция
startTransition
(или хук useTransition
) позволяет явно указать "не срочные" обновления. Их выполнение может быть прервано, если в процессе поступят какие-то "срочные" обновления. Suspense
Расширились возможности React.Suspense. Раньше он только позволял лениво загружать код с помощью React.lazy и не поддерживался при серверном рендеринге. Теперь работает и на сервере тоже и хорошо сочетается с API переходов.
Новые API рендеринга
Новые методы для рендеринга -
createRoot
и hydrateRoot`на клиенте, `renderToPipeableStream
и renderToReadableStream
на сервере.Двойное монтирование компонентов
В строгом режиме в dev mode добавлена проверка на "устойчивость к многократному монтированию" - компоненты в первый раз монтируются, сразу размонтируются с сохранением состояния и монтируются снова. Это нужно для будущих улучшений.
Новые хуки
-
useId
- генерация уникальных идентификаторов-
useTransition
- позволяет пометить обновления как "переходные" (см. выше)-
useDeferredValue
- откладывает не срочный перерендеринг-
useSyncExternalStore
- хук для библиотек, работающих с внешним состоянием-
useInsertionEffect
- хук для библиотек CSS-in-JS для инъекции стилей, срабатывает до layout effect.#react
Хабр
React 18
В нашем последнем посте мы поделились пошаговыми инструкциями по обновлению вашего приложения до React 18 . В текущем посте мы дадим обзор того, что нового появилось в React 18, и что это означает для...
👍1
Что мне не нравится в react-router
Статья (рус.): https://habr.com/ru/post/599347/
Мнение разработчика о недостатках React Router. Местами субъективно (точка зрения относительно больших сложных проектов), но в любом случае интересно и полезно для ознакомления. Претензии в основном к старой версии библиотеки, в последнем релизе появилось много полезных фич.
Главные претензии:
1. JSX плохо подходит для описания конфига роутинга. Удобнее работать с обычным JSON.
2. Отсутствие модульности, сложности с формированием сложных ссылок "от корня".
3. Лишние перерендеры одинаковых компонентов в разных роутах.
В комментариях тоже интересно.
#роутинг #ссылки
Статья (рус.): https://habr.com/ru/post/599347/
Мнение разработчика о недостатках React Router. Местами субъективно (точка зрения относительно больших сложных проектов), но в любом случае интересно и полезно для ознакомления. Претензии в основном к старой версии библиотеки, в последнем релизе появилось много полезных фич.
Главные претензии:
1. JSX плохо подходит для описания конфига роутинга. Удобнее работать с обычным JSON.
2. Отсутствие модульности, сложности с формированием сложных ссылок "от корня".
3. Лишние перерендеры одинаковых компонентов в разных роутах.
В комментариях тоже интересно.
#роутинг #ссылки
Хабр
Что мне не нравится в react-router
Недавно меня спросили: “Зачем я отказался от библиотеки react-router и перешел на свой велосипед?” Честно говоря, вопросы, связанные с моим вариантом роутинга, мне задавали уже раз пять. Последний раз...
👍1
Redux Essentials 12. Уведомления
Добавляем функционал уведомлений - страницу со списком и возможность обновить список (получить "новые" уведомления), нажав на кнопку.
https://codesandbox.io/s/redux-essentials-notifications-react-junior-qmk9tf
Так как это просто демка Redux, уведомления будут довольно куцые.
API
В фейковый апи добавлен метод для генерации рандомных сообщений. Он получает время последнего сообщения и создает несколько "новых" сообщений.
Слайс
Добавляем новую фичу
Этот фрагмент состояния представляет собой простой массив уведомлений, никакие статусы тут отслеживаться не будут.
Экшен всего один -
Есть два селектора -
Thunk
Добавляем также thunk creator
Из интересного - функция принимает два параметра - первый пользовательский, если в thunk нужно передать какие-то данные, второй -
Нужно также добавить редьюсер для экшена
Список
Добавляем компонент
Кроме того, добавляем в
#redux #управлениесостоянием #документация #примерыкода
Добавляем функционал уведомлений - страницу со списком и возможность обновить список (получить "новые" уведомления), нажав на кнопку.
https://codesandbox.io/s/redux-essentials-notifications-react-junior-qmk9tf
Так как это просто демка Redux, уведомления будут довольно куцые.
API
В фейковый апи добавлен метод для генерации рандомных сообщений. Он получает время последнего сообщения и создает несколько "новых" сообщений.
Слайс
Добавляем новую фичу
features/notifications
и создаем новый слайс, который нужно будет добавить в метод configureStore
в app/store.js
.Этот фрагмент состояния представляет собой простой массив уведомлений, никакие статусы тут отслеживаться не будут.
Экшен всего один -
allNotificationsRead
. У каждого уведомления будет статус "прочитано/не прочитано", чтобы можно было подсвечивать новые. Этот экшен будет помечать все обновления прочитанными.Есть два селектора -
getNotifications
и getUnreadNotificationsCount
.Thunk
Добавляем также thunk creator
fetchNotifications
, который будет обращаться к "серверу" и получать новые уведомления.Из интересного - функция принимает два параметра - первый пользовательский, если в thunk нужно передать какие-то данные, второй -
thunkAPI
- объект с методами для работы с хранилищем (getStore
, dispatch
).Нужно также добавить редьюсер для экшена
fetchNotifications.fulfilled
в секцию extraReducers
. Раньше мы всегда оформляли ее как функцию и добавляли все обработчики через объект builder
. Но тут используется другой синтаксис - объект, поля которого представляют собой имена экшенов. Так тоже можно.extraReducers: {Выглядит более понятно, чем вариант с функцией, но тот обычно удобнее.
[fetchNotifications.fulfilled]: function(state, action) {}
}
Список
Добавляем компонент
NotificationsList
, который будет рендерить список уведомлений, а также помечать все уведомления прочитанными. Для этого используем хук useLayoutEffect.Кроме того, добавляем в
App.js
новый роут notifications
, а в шапку - новую ссылку. Плюс в шапке еще появилась кнопка для обновления списка (получения новых уведомлений). Если ее нажать, появится количество непрочитанных сообщений, которое обнулится при переходе на страницу списка.#redux #управлениесостоянием #документация #примерыкода
CodeSandbox
Redux Essentials. Notifications. React Junior - CodeSandbox
Redux Essentials. Notifications. React Junior by furrycat.web using @reduxjs/toolkit, date-fns, react, react-dom, react-redux, react-router-dom, react-scripts, styled-components
Redux Essentials 13. Мемоизация селекторов
В текущей версии проекта (https://qmk9tf.csb.app/users/1) перейдем на страницу пользователя, откроем в панели разработчика вкладку Profiler (из React DevTools) и нажмем на кнопку записи.
Теперь обновим список уведомлений (кнопка в шапке) и после этого остановим запись.
Увидим, что помимо шапки (в которой появилось кол-во непрочитанных сообщений), перерендерилась еще и страница
Впрочем, мы уже знаем, в чем дело - в селекторе
Чтобы решить проблему, используем метод createSelector (из библиотеки reselect, берем из пакета @reduxjs/toolkit).
У него будут два входных селектора - уже существующий
Обновленный код проекта: https://codesandbox.io/s/redux-essentials-memoized-selectors-react-junior-e8u8e6?file=/src/features/posts/postsSlice.js
Сам проект: https://e8u8e6.csb.app/users/1
#redux #управлениесостоянием #документация #примерыкода
В текущей версии проекта (https://qmk9tf.csb.app/users/1) перейдем на страницу пользователя, откроем в панели разработчика вкладку Profiler (из React DevTools) и нажмем на кнопку записи.
Теперь обновим список уведомлений (кнопка в шапке) и после этого остановим запись.
Увидим, что помимо шапки (в которой появилось кол-во непрочитанных сообщений), перерендерилась еще и страница
UserPage
. Казалось бы, с чего это вдруг, в этом компоненте изменений не было. Впрочем, мы уже знаем, в чем дело - в селекторе
getUserPosts
, который возвращает новый массив, так как используем метод filter
.Чтобы решить проблему, используем метод createSelector (из библиотеки reselect, берем из пакета @reduxjs/toolkit).
У него будут два входных селектора - уже существующий
getPosts
, который возвращает массив всех статей, и еще один, который возвращает только id пользователя. Выходной селектор уже фильтрует полученный массив. Таким образом, если общий список не изменится, перерендера не будет.Обновленный код проекта: https://codesandbox.io/s/redux-essentials-memoized-selectors-react-junior-e8u8e6?file=/src/features/posts/postsSlice.js
Сам проект: https://e8u8e6.csb.app/users/1
#redux #управлениесостоянием #документация #примерыкода
👍1
Redux Essentials 14. Мемоизация компонентов
Еще одна проблема производительности в текущей версии проекта (https://qmk9tf.csb.app/).
Если на главной странице (со списком постов) поставить реакцию под одной из статей, то перерендерятся ВСЕ статьи, а не только та, которая изменилась.
Дело в том, что при изменении одного объекта статьи меняется весь массив статей. Из-за этого перерендеривается весь компонент
Есть несколько способов решить эту проблему.
Первый - обернуть компонент
Обновленный код проекта: https://codesandbox.io/s/redux-essentials-memoized-selectors-react-junior-e8u8e6?file=/src/features/posts/PostsList.js
Сам проект: https://e8u8e6.csb.app/
Второй - переписать селектор
Третий - переделать состояние в целом, чтобы в нем хранился массив айдишников, который изменяется только при изменении набора постов. Другими словами, нормализовать состояние. Этим займемся в следующий раз.
#redux #управлениесостоянием #документация #примерыкода
Еще одна проблема производительности в текущей версии проекта (https://qmk9tf.csb.app/).
Если на главной странице (со списком постов) поставить реакцию под одной из статей, то перерендерятся ВСЕ статьи, а не только та, которая изменилась.
Дело в том, что при изменении одного объекта статьи меняется весь массив статей. Из-за этого перерендеривается весь компонент
PostsList
, а с ним и все его потомки.Есть несколько способов решить эту проблему.
Первый - обернуть компонент
PostExcerpt
в React.memo
. Тогда он не будет перерендериваться при перерендере родителя (если у него не поменяются пропсы).Обновленный код проекта: https://codesandbox.io/s/redux-essentials-memoized-selectors-react-junior-e8u8e6?file=/src/features/posts/PostsList.js
Сам проект: https://e8u8e6.csb.app/
Второй - переписать селектор
getPosts
, чтобы он возвращал только айдишники статей, и мемоизировать его с помощью shallowEqual. А в компоненте PostExcerpt
получать только id
и по нему находить нужный пост.Третий - переделать состояние в целом, чтобы в нем хранился массив айдишников, который изменяется только при изменении набора постов. Другими словами, нормализовать состояние. Этим займемся в следующий раз.
#redux #управлениесостоянием #документация #примерыкода
👍1
Плохие привычки Middle React разработчиков
Статья (англ.): https://dev.to/srmagura/bad-habits-of-mid-level-react-developers-b41
Автор статьи перечисляет частые ошибки и плохие практики, которые видит, делая ревью чужого кода. В комментариях согласны не со всем :)
Итак, React-разработчики часто:
👎 Дублируют состояние
Плохо выглядит и может привести к рассинхрону.
👎 Не используют редьюсеры
Для работы с более-менее сложным состоянием редьюсеры (useReducer, redux) предпочтительнее простого useState. В частности, автор рекомендует работать через редьюсер с любым массивом, который можно редактировать.
👎 Не пишут юнит-тесты
Речь в статье идет о тестах, написание которых не занимает много времени, но приносит большую пользу, например, о тестах для редьюсеров.
👎 Недостаточно используют React.memo, useMemo и useCallback
Что приводит к проблемам с производительностью.
👎 Неправильно используют useEffect
Эффект запускается либо слишком часто, либо недостаточно часто. Из полезного: автор рекомендует помещать функции, которые задействованы в эффекте в useRef, чтобы сохранять их идентичность.
👎 Забывают про юзабилити
Не связано напрямую с React и вообще много где встречается.
👎 Не стремятся к совершенствованию знаний в CSS и веб-дизайне
Добавка к предыдущему пункту.
В заключение автор дает несколько советов-"хороших практик":
👍 Использовать исключительно TypeScript
👍 Использовать библиотеку для запросов (data-fetching)
👍 Использовать серверный рендеринг, только если он вам действительно нужен
👍 Использовать модульный CSS и связывать стили с компонентами
#ссылки #паттерны
Статья (англ.): https://dev.to/srmagura/bad-habits-of-mid-level-react-developers-b41
Автор статьи перечисляет частые ошибки и плохие практики, которые видит, делая ревью чужого кода. В комментариях согласны не со всем :)
Итак, React-разработчики часто:
👎 Дублируют состояние
Плохо выглядит и может привести к рассинхрону.
👎 Не используют редьюсеры
Для работы с более-менее сложным состоянием редьюсеры (useReducer, redux) предпочтительнее простого useState. В частности, автор рекомендует работать через редьюсер с любым массивом, который можно редактировать.
👎 Не пишут юнит-тесты
Речь в статье идет о тестах, написание которых не занимает много времени, но приносит большую пользу, например, о тестах для редьюсеров.
👎 Недостаточно используют React.memo, useMemo и useCallback
Что приводит к проблемам с производительностью.
👎 Неправильно используют useEffect
Эффект запускается либо слишком часто, либо недостаточно часто. Из полезного: автор рекомендует помещать функции, которые задействованы в эффекте в useRef, чтобы сохранять их идентичность.
👎 Забывают про юзабилити
Не связано напрямую с React и вообще много где встречается.
👎 Не стремятся к совершенствованию знаний в CSS и веб-дизайне
Добавка к предыдущему пункту.
В заключение автор дает несколько советов-"хороших практик":
👍 Использовать исключительно TypeScript
👍 Использовать библиотеку для запросов (data-fetching)
👍 Использовать серверный рендеринг, только если он вам действительно нужен
👍 Использовать модульный CSS и связывать стили с компонентами
#ссылки #паттерны
DEV Community
Bad Habits of Mid-Level React Developers
If you're a mid-level React developer looking to become an advanced React developer, this post is for...
👍3❤1