Доступен React 18 RC
Версия React 18 стала доступна в качестве релиз-кандидата. Чтобы установить, нужно использовать
В React 18 появится новое API для библиотек. Для поддержки конкурентного рендеринга сторонними библиотеками было добавлено следующее API:
- useId – хук для генерации уникального id на клиенте и сервере, поддерживающего гидратацию. Подробнее.
- useSyncExternalStore – хук для работы с внешними хранилищами, позволяющий производить параллельное чтение из источника и синхронную запись. Подробнее.
- useInsertionEffect – хук для вставки стилей в процессе рендера, предназначен для CSS-in-JS библиотек. Подробнее.
Новые изменения в строгом режиме (strict mode). В будущем React планирует поддерживать пользовательский UI, в котором части интерфейса можно будет удалить с сохранением стейта, чтобы потом их можно было восстановить. Например, переключение табов на странице, когда при смене таба нужный компонент будет отображаться сразу с восстановленным состоянием.
Для поддержки такого UI сценария React добавляет новую проверку в development режиме в strict mode. Эта новая проверка будет автоматически демонтировать и повторно монтировать каждый компонент всякий раз, когда компонент монтируется в первый раз, восстанавливая предыдущее состояние при втором монтировании.
Также в React 18 прекращается поддержка браузера Internet Explorer.
https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
Версия React 18 стала доступна в качестве релиз-кандидата. Чтобы установить, нужно использовать
@rc тег:
npm install react@rc react-dom@rc
// или
yarn add react@rc react-dom@rc
В React 18 появится новое API для библиотек. Для поддержки конкурентного рендеринга сторонними библиотеками было добавлено следующее API:
- useId – хук для генерации уникального id на клиенте и сервере, поддерживающего гидратацию. Подробнее.
- useSyncExternalStore – хук для работы с внешними хранилищами, позволяющий производить параллельное чтение из источника и синхронную запись. Подробнее.
- useInsertionEffect – хук для вставки стилей в процессе рендера, предназначен для CSS-in-JS библиотек. Подробнее.
Новые изменения в строгом режиме (strict mode). В будущем React планирует поддерживать пользовательский UI, в котором части интерфейса можно будет удалить с сохранением стейта, чтобы потом их можно было восстановить. Например, переключение табов на странице, когда при смене таба нужный компонент будет отображаться сразу с восстановленным состоянием.
Для поддержки такого UI сценария React добавляет новую проверку в development режиме в strict mode. Эта новая проверка будет автоматически демонтировать и повторно монтировать каждый компонент всякий раз, когда компонент монтируется в первый раз, восстанавливая предыдущее состояние при втором монтировании.
Также в React 18 прекращается поддержка браузера Internet Explorer.
https://reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
GitHub
Intent to Ship: useId · reactwg/react-18 · Discussion #111
This feature is now available in the latest alphas facebook/react#22644 useId is an API for generating unique IDs on both the client and server, while avoiding hydration mismatches. We haven't ...
👍7
История React
На канале uidotdev вышло видео об истории React, о том как он возник в 2013 году и стал тем, чем является сейчас.
https://www.youtube.com/watch?v=Wm_xI7KntDs
На канале uidotdev вышло видео об истории React, о том как он возник в 2013 году и стал тем, чем является сейчас.
https://www.youtube.com/watch?v=Wm_xI7KntDs
YouTube
The Story of React
This is the story of how React took over the world.
👍3
Структура проекта React от Джошуа Комо
В React нет единого подхода к организации структуры проекта, поэтому у многих начинающих разработчиков возникает вопрос, как правильно? Один из советов Дэна Абрамова – “перемещайте файлы, пока не почувствуете, что это правильно”.
Джошуа Комо поделился своей структурой проекта, которую он использует на всех своих проектах. Основные особенности этой структуры:
- Использование абсолютного импорта.
- Название файла по имени компонента.
- Хранение файлов в папках по функциям, а не по фичам.
- Хранение хуков, констант и хелперов для компонента в отдельных файлах рядом.
https://www.joshwcomeau.com/react/file-structure/
В React нет единого подхода к организации структуры проекта, поэтому у многих начинающих разработчиков возникает вопрос, как правильно? Один из советов Дэна Абрамова – “перемещайте файлы, пока не почувствуете, что это правильно”.
Джошуа Комо поделился своей структурой проекта, которую он использует на всех своих проектах. Основные особенности этой структуры:
- Использование абсолютного импорта.
- Название файла по имени компонента.
- Хранение файлов в папках по функциям, а не по фичам.
- Хранение хуков, констант и хелперов для компонента в отдельных файлах рядом.
https://www.joshwcomeau.com/react/file-structure/
👎15👍9
Как проектировалось мидлвар подписки для Redux Toolkit
В Redux Toolkit 1.8 вышло новое API
В своем блоге один из разработчиков Redux Toolkit, Марк Эриксон, рассказал об истории данного API и этапах его разработки. Разработка данной фичи была начата 2.5 года назад и потребовала много итераций, чтобы определить, какие варианты использования он должен охватывать, как должен выглядеть общедоступный API и как реализовать функциональность.
В основе у Redux есть несколько основных библиотек для работы с сайд эффектами:
- Thunks: отправить экшен, получить (dispatch, getState) в аргументах и выполнить любую логику внутри функции.
- Sagas: напишите функцию генератор, которая на экшен вызывает сайд эффект функцию.
- Observables: напишите RxJs пайплайн, который на экшен вызывает сайд эффект функцию.
По умолчанию в Redux Toolkit был выбран Thunks, как самый простой вариант работы с сайд эффектами. При разработке API
https://blog.isquaredsoftware.com/2022/03/designing-rtk-listener-middleware/
В Redux Toolkit 1.8 вышло новое API
createListenerMiddleware для подписки на отправку экшенов или изменения стейта. Это API должно стать более простой альтернативой использования вместо более популярных saga или observable.
// Create the middleware instance and methods
const listenerMiddleware = createListenerMiddleware()
// Add one or more listener entries that look for specific actions.
// They may contain any sync or async logic, similar to thunks.
listenerMiddleware.startListening({
actionCreator: todoAdded,
effect: async (action, listenerApi) => {
// Run whatever additional side-effect-y logic you want here
console.log('Todo added: ', action.payload.text)
// Can cancel other running instances
listenerApi.cancelActiveListeners()
// Run async logic
const data = await fetchData()
// Pause until action dispatched or state changed
if (await listenerApi.condition(matchSomeAction)) {
// Use the listener API methods to dispatch, get state,
// unsubscribe the listener, start child tasks, and more
listenerApi.dispatch(todoAdded('Buy pet food'))
listenerApi.unsubscribe()
}
},
})
В своем блоге один из разработчиков Redux Toolkit, Марк Эриксон, рассказал об истории данного API и этапах его разработки. Разработка данной фичи была начата 2.5 года назад и потребовала много итераций, чтобы определить, какие варианты использования он должен охватывать, как должен выглядеть общедоступный API и как реализовать функциональность.
В основе у Redux есть несколько основных библиотек для работы с сайд эффектами:
- Thunks: отправить экшен, получить (dispatch, getState) в аргументах и выполнить любую логику внутри функции.
- Sagas: напишите функцию генератор, которая на экшен вызывает сайд эффект функцию.
- Observables: напишите RxJs пайплайн, который на экшен вызывает сайд эффект функцию.
По умолчанию в Redux Toolkit был выбран Thunks, как самый простой вариант работы с сайд эффектами. При разработке API
createListenerMiddleware команда Redux Toolkit хотела отделить экшены и сайд эффекты, т.е. смотрела в сторону redux-saga. Однако по сложности пользовательского API была цель сделать его близким к redux-thunk.https://blog.isquaredsoftware.com/2022/03/designing-rtk-listener-middleware/
Mark's Dev Blog
Idiomatic Redux: Designing the Redux Toolkit Listener Middleware
A dive into how we designed the API for the new RTK listener middleware
👍5
Тинькофф представил React фреймворк tramvai
Компания Тинькофф выложила в opensource свой React фреймворк для создания SSR приложений tramvai. Фреймворк похож на node.js фреймворк Nest.js, в нем также есть DI и модули.
Главная особенность фреймворка – очень большое количество уже готовых библиотек, которая создает целую экосистему, с помощью которой можно создавать enterprise приложения. В качестве отдельных модулей есть роутер, библиотека для тестирования, стейт менеджер, логгер и другие. Все модули подключаются к приложению через DI.
Выглядит очень необычно. Будет ли пользоваться спросом данный фреймворк где-то за пределами проектов Тинькофф – вопрос интересный.
https://tramvai.dev/
https://habr.com/ru/post/655953/
Компания Тинькофф выложила в opensource свой React фреймворк для создания SSR приложений tramvai. Фреймворк похож на node.js фреймворк Nest.js, в нем также есть DI и модули.
Главная особенность фреймворка – очень большое количество уже готовых библиотек, которая создает целую экосистему, с помощью которой можно создавать enterprise приложения. В качестве отдельных модулей есть роутер, библиотека для тестирования, стейт менеджер, логгер и другие. Все модули подключаются к приложению через DI.
Выглядит очень необычно. Будет ли пользоваться спросом данный фреймворк где-то за пределами проектов Тинькофф – вопрос интересный.
https://tramvai.dev/
https://habr.com/ru/post/655953/
👍14👎1
Аналоги Storybook
Storybook предназначен для помощи в разработке и тестировании компонентов в изолированной среде. Также в Storybook можно хранить примеры использования компонентов и документацию по компонентам.
Если вас не устраивает Storybook, то можно обратить внимание на аналоги:
React Cosmos
- Песочница как в Storybook. Возможность разработки компонентов в изоляции.
- Помощь в организации библиотеки компонентов. Возможность установки любых пропсов для компонентов.
- Удобный интерфейс. Есть возможность просмотра компонента в разных размерах окна.
React Styleguidist
- Автогенерация документации. Интерактивные примеры.
- Возможность написания примеров в Markdown разметке.
- Удобен для создания документации библиотеки компонентов.
Ladle
- Создан как замена Storybook разработчиками из Uber. Можно использовать в уже существующем проекте с историями Storybook.
- Production сборка проекта в 4 раза быстрее чем Storybook. Использует code splitting для разделения историй.
- Позволяет сохранять состояние компонента в URL – полезно для тестирования.
Storybook предназначен для помощи в разработке и тестировании компонентов в изолированной среде. Также в Storybook можно хранить примеры использования компонентов и документацию по компонентам.
Если вас не устраивает Storybook, то можно обратить внимание на аналоги:
React Cosmos
- Песочница как в Storybook. Возможность разработки компонентов в изоляции.
- Помощь в организации библиотеки компонентов. Возможность установки любых пропсов для компонентов.
- Удобный интерфейс. Есть возможность просмотра компонента в разных размерах окна.
React Styleguidist
- Автогенерация документации. Интерактивные примеры.
- Возможность написания примеров в Markdown разметке.
- Удобен для создания документации библиотеки компонентов.
Ladle
- Создан как замена Storybook разработчиками из Uber. Можно использовать в уже существующем проекте с историями Storybook.
- Production сборка проекта в 4 раза быстрее чем Storybook. Использует code splitting для разделения историй.
- Позволяет сохранять состояние компонента в URL – полезно для тестирования.
reactcosmos.org
React Cosmos
Sandbox for developing and testing UI components in isolation.
👍8
Критический путь рендеринга
Критический путь рендеринга – это шаги от получения браузером HTML и до отрисовки страницы пользователю. Для того, чтобы этот процесс был быстрым, необходима оптимизация этих шагов.
При парсинге HTML браузер строит DOM дерево, для CSS строится CSSOM дерево. Если при парсинге HTML будет обнаружен JS, то он будет выполнен (если это не модуль или нет атрибута defer). Стили и JS скрипты являются блокирующими для парсера ресурсами, что может сказаться на времени критического пути рендеринга.
Чтобы ускорить время критического пути рендеринга, нужно делать оптимизацию:
- Сократить CSS ресурсы для первоначальной загрузки. Стили, которые не нужны для просмотра текущей страницы, можно загрузить после.
- Используйте ленивую загрузку. Разделяйте страницы сайта на части.
- Используйте Async, Defer, Preload для скриптов.
- Кэширование ресурсов. Можно использовать заголовки ETag, Cache-Control, Last-Modified, Expires для валидации кэша в браузере, а также ServiceWorker для ручного кэширования нужных ресурсов.
При разработке на React также стоит соблюдать правила оптимизации:
- Используйте lazy loading роуты.
- Условный рендер компонентов. Если компонент тяжелый и ,например, открывается по клику на кнопку, то можно загружать его по потребности.
https://indepth.dev/posts/1498/101-javanoscript-critical-rendering-path
Критический путь рендеринга – это шаги от получения браузером HTML и до отрисовки страницы пользователю. Для того, чтобы этот процесс был быстрым, необходима оптимизация этих шагов.
При парсинге HTML браузер строит DOM дерево, для CSS строится CSSOM дерево. Если при парсинге HTML будет обнаружен JS, то он будет выполнен (если это не модуль или нет атрибута defer). Стили и JS скрипты являются блокирующими для парсера ресурсами, что может сказаться на времени критического пути рендеринга.
Чтобы ускорить время критического пути рендеринга, нужно делать оптимизацию:
- Сократить CSS ресурсы для первоначальной загрузки. Стили, которые не нужны для просмотра текущей страницы, можно загрузить после.
- Используйте ленивую загрузку. Разделяйте страницы сайта на части.
- Используйте Async, Defer, Preload для скриптов.
- Кэширование ресурсов. Можно использовать заголовки ETag, Cache-Control, Last-Modified, Expires для валидации кэша в браузере, а также ServiceWorker для ручного кэширования нужных ресурсов.
При разработке на React также стоит соблюдать правила оптимизации:
- Используйте lazy loading роуты.
- Условный рендер компонентов. Если компонент тяжелый и ,например, открывается по клику на кнопку, то можно загружать его по потребности.
https://indepth.dev/posts/1498/101-javanoscript-critical-rendering-path
👍8❤1
Релиз React 18
На npm появилась стабильная 18 версия React.
В новой версии React появился автоматический батчинг, новое API, такое как startTransition, потоковый серверный рендер с использованием Suspense и другие улучшения.
Многие новые фичи в React 18 сделаны на основе нового конкурентного рендеринга. Особенность в том, что конкурентный рендеринг включается только тогда, когда используются фичи из его набора.
Также появились новые хуки:
- useId для генерации уникального ID на клиенте и сервере, чтобы избежать проблем с гидратацией.
- useTransition и startTransition для несрочных изменений стейта.
- useDeferredValue для несрочного рендера значений.
https://reactjs.org/blog/2022/03/29/react-v18.html
На npm появилась стабильная 18 версия React.
В новой версии React появился автоматический батчинг, новое API, такое как startTransition, потоковый серверный рендер с использованием Suspense и другие улучшения.
Многие новые фичи в React 18 сделаны на основе нового конкурентного рендеринга. Особенность в том, что конкурентный рендеринг включается только тогда, когда используются фичи из его набора.
Также появились новые хуки:
- useId для генерации уникального ID на клиенте и сервере, чтобы избежать проблем с гидратацией.
- useTransition и startTransition для несрочных изменений стейта.
- useDeferredValue для несрочного рендера значений.
https://reactjs.org/blog/2022/03/29/react-v18.html
react.dev
React v18.0 – React
The library for web and native user interfaces
🔥13
Как работают роуты в Remix
В Remix используется роутинг на основе файловой системы. Внутри папки с роутами каждый файл представляет собой отдельную страницу. Внутри каждого файла есть несколько экспортов. Дефолтный эскпорт - это React компонент, а специальные методы Remix экспортируются по имени. Среди таких экспортов может быть получение данных loader или мутация action.
В Remix можно создавать общий шаблон для страниц:
В файле posts.jsx используется Remix компонент
Для создания динамического роута необходимо начать имя файла со знака
Также можно определять дополнительные сегменты пути роута через точку. Теперь компонент
Если нужно создать роут, который бы открывался по любому пути, нужно создать файл с названием
https://www.smashingmagazine.com/2022/03/remix-routes-demystified/
В Remix используется роутинг на основе файловой системы. Внутри папки с роутами каждый файл представляет собой отдельную страницу. Внутри каждого файла есть несколько экспортов. Дефолтный эскпорт - это React компонент, а специальные методы Remix экспортируются по имени. Среди таких экспортов может быть получение данных loader или мутация action.
В Remix можно создавать общий шаблон для страниц:
├───/apps
│ ├───/routes
│ │ ├───/posts // компоненты постов
│ │ └───posts.jsx // это шаблон
В файле posts.jsx используется Remix компонент
<Outlet />, который вместо себя рендерит вложенные компоненты, как в react-router.
├───/apps
│ ├───/routes
│ | └───/users
│ | ├───$userId.edit.jsx
│ | ├───$userId.jsx
│ │ └───$.jsx
Для создания динамического роута необходимо начать имя файла со знака
$. Чтобы получить название параметра в компоненте нужно использовать хук: const { userId } = useParams().Также можно определять дополнительные сегменты пути роута через точку. Теперь компонент
$userId.edit.jsx будет открываться по пути /users/{{user-id}}/edit. Если нужно создать роут, который бы открывался по любому пути, нужно создать файл с названием
$.jsx. Тогда, если нет подходящего роута по данному URL, будет открываться $.jsx.https://www.smashingmagazine.com/2022/03/remix-routes-demystified/
Smashing Magazine
Remix Routes Demystified — Smashing Magazine
In the past months, there have been lots of talks dedictaed to Remix. Routing is not only one of the things that sets it apart from other frameworks, but it also fuels great performance and improves the overall experience for developers. Let’s dig in to all…
👍5
Когда React рендерит компонент
Чтобы эффективно создавать приложения на React, полезно понимать поведение рендеринга React и знать правила как избежать повторный рендер.
React рендерит компонент, если:
- у компонента запланировано обновление стейта.
- произошел рендер родительского компонента и текущий компонент не соответствует критериям отказа от повторного рендера, где все эти четыре условия должны выполняться одновременно:
- Компонент был уже отрендерен и смонтирован.
- Нет изменений пропсов.
- Нет изменений в значении контекста, который используется в компоненте.
- Сам компонент не запланировал обновление.
Существуют два типа рендеринга, которые могут произойти с компонентом:
- активный рендеринг:
- Компонент (или кастомный хук) заранее планирует обновления для изменения стейта.
- Прямой вызов ReactDOM.render.
- пассивный рендеринг: родительский компонент запланировал обновление стейта и текущий компонент не соответствует критериям отказа от повторного рендера (четыре условия выше).
https://www.zhenghao.io/posts/react-rerender
Чтобы эффективно создавать приложения на React, полезно понимать поведение рендеринга React и знать правила как избежать повторный рендер.
React рендерит компонент, если:
- у компонента запланировано обновление стейта.
- произошел рендер родительского компонента и текущий компонент не соответствует критериям отказа от повторного рендера, где все эти четыре условия должны выполняться одновременно:
- Компонент был уже отрендерен и смонтирован.
- Нет изменений пропсов.
- Нет изменений в значении контекста, который используется в компоненте.
- Сам компонент не запланировал обновление.
Существуют два типа рендеринга, которые могут произойти с компонентом:
- активный рендеринг:
- Компонент (или кастомный хук) заранее планирует обновления для изменения стейта.
- Прямой вызов ReactDOM.render.
- пассивный рендеринг: родительский компонент запланировал обновление стейта и текущий компонент не соответствует критериям отказа от повторного рендера (четыре условия выше).
https://www.zhenghao.io/posts/react-rerender
zhenghao.io
When does React render your component?
When and why does React render my component exactly?
👍13
Как React 18 может сломать ваше приложение
Уже сейчас можно обновить библиотеку React до 18 версии, и разработчики утверждают, что обновление должно быть безболезненным. Однако, иногда после обновления могут происходить ошибки в приложениях. Связано это с новым режимом работы StrictMode.
В dev режиме React будет делать проверку, автоматически размонтировать и повторно монтировать каждый компонент всякий раз, когда компонент монтируется в первый раз, восстанавливая предыдущее состояние стейтов при втором монтировании. Это необходимо, чтобы в будущем React мог удалять и восстанавливать секции UI с сохранением стейта. Например, при переключении табов на странице. Как работают эффекты в таком режиме:
Для поддержки данной фичи необходимо, чтобы эффекты в компоненте были стабильны, т.е., например, созданный ресурс в эффекте удалялся в функции очистки.
С появлением подобного режима и при неправильной реализации useEffect могут появиться баги в приложении.
Например, хук выше определяет, смонтирован ли компонент. В React 18 данный хук будет работать неправильно, т.к. при проверке стабильности эффектов React будет несколько раз запускать и очищать useEffect. Чтобы исправить хук, нужно добавить присвоение в самом эффекте:
Уже сейчас можно обновить библиотеку React до 18 версии, и разработчики утверждают, что обновление должно быть безболезненным. Однако, иногда после обновления могут происходить ошибки в приложениях. Связано это с новым режимом работы StrictMode.
В dev режиме React будет делать проверку, автоматически размонтировать и повторно монтировать каждый компонент всякий раз, когда компонент монтируется в первый раз, восстанавливая предыдущее состояние стейтов при втором монтировании. Это необходимо, чтобы в будущем React мог удалять и восстанавливать секции UI с сохранением стейта. Например, при переключении табов на странице. Как работают эффекты в таком режиме:
* React mounts the component.
* Layout effects are created.
* Effect effects are created.
* React simulates effects being destroyed on a mounted component.
* Layout effects are destroyed.
* Effects are destroyed.
* React simulates effects being re-created on a mounted component.
* Layout effects are created
* Effect setup code runs
Для поддержки данной фичи необходимо, чтобы эффекты в компоненте были стабильны, т.е., например, созданный ресурс в эффекте удалялся в функции очистки.
С появлением подобного режима и при неправильной реализации useEffect могут появиться баги в приложении.
function useIsMounted() {
const isMountedRef = React.useRef(true);
React.useEffect(() => {
return () => {
isMountedRef.current = false;
};
}, []);
return () => isMountedRef.current;
}
Например, хук выше определяет, смонтирован ли компонент. В React 18 данный хук будет работать неправильно, т.к. при проверке стабильности эффектов React будет несколько раз запускать и очищать useEffect. Чтобы исправить хук, нужно добавить присвоение в самом эффекте:
React.useEffect(() => {
isMountedRef.current = true;
return () => {
isMountedRef.current = false;
};
}, []);
legacy.reactjs.org
Strict Mode – React
A JavaScript library for building user interfaces
👍9
Изменения типов в React 18
Вышло мажорное обновление библиотеки типов для React 18
- Убран неявный проп children в React.FC и React.Component. Теперь, если компонент ожидает проп children, то его нужно передавать явно:
Есть несколько причин, почему был удален проп children. Во первых, очень часто этот проп не использовался. Но так как он был объявлен в типах, то это могло приводить к неверным предположениям о работе компонента (раз есть проп children, то значит он как-то используется внутри компонента). Во вторых, более строгая типизация пропа children, теперь можно самостоятельно указать его тип. Более подробно про причины удаления неявного children написано здесь.
- Убран тип
-
- Удалены неиспользуемые типы. Приведены к общей терминологии, как они называются в репозитории и документации:
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210
Вышло мажорное обновление библиотеки типов для React 18
@types/react@^18.0.0. В нем есть несколько критических изменений:- Убран неявный проп children в React.FC и React.Component. Теперь, если компонент ожидает проп children, то его нужно передавать явно:
interface Props {
children?: React.ReactNode;
}
const SomeFunctionComponent: React.FC<Props> = props => <div>{props.children}</div>
Есть несколько причин, почему был удален проп children. Во первых, очень часто этот проп не использовался. Но так как он был объявлен в типах, то это могло приводить к неверным предположениям о работе компонента (раз есть проп children, то значит он как-то используется внутри компонента). Во вторых, более строгая типизация пропа children, теперь можно самостоятельно указать его тип. Более подробно про причины удаления неявного children написано здесь.
- Убран тип
{} у ReactFragment. Это никогда не было правильным и в основном требовалось для взаимодействия с неявными пропом children.-
this.context по умолчанию станет unknown. Раньше по умолчанию был any. Это распространяется и на функцию useCallback, теперь, если тип не указан, то по умолчанию аргумент будет unknown.- Удалены неиспользуемые типы. Приведены к общей терминологии, как они называются в репозитории и документации:
-StatelessComponent
+FunctionComponent
-SFC
+FC
-React.ReactType
+React.ElementType
-SFCElement
+FunctionComponentElement
// без замены
-Props
-RefForwardingComponent
-SFCFactory
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/56210
solverfox.dev
Removal of implicit children
Explainer why we intend to get rid of implicit children in `@types/react`
👍12
Композиция компонентов в React: как сделать это правильно
При разработке приложения на React возникает сложность в разделении компонентов и их правильной композиции между собой. Некоторые разработчики не разделяют компонент на более мелкие и получают большой компонент-монолит, который в дальнейшем сложно поддерживать. Также некоторые разработчики начинают разделять компонент на более мелкие подкомпоненты слишком рано, что приводит к оверинженирингу и сложно поддерживаемому коду.
В React есть несколько подходов к композиции компонентов. Есть “простые” компоненты:
И компоненты контейнеры:
У компонента контейнера вместо пропса noscript проп children. Это различие позволяет более гибко использовать компонент контейнер и передавать в children любые элементы, при этом синтаксис выглядит как использование обычного HTML тега.
Можно определить следующие правила для декомпозиции компонента:
- Начинайте реализацию “сверху вниз”. Если делать “снизу вверх”, т.е. сначала создавать небольшие переиспользуемые компоненты, то возможно у вас получится компонент со слишком сложным API и будет отсутствовать половина нужного функционала.
- Создавайте подкомпонент только тогда, когда в этом есть необходимость. Одно из возможных причин, когда компонент нужно декомпозировать – это его размер.
- Начинайте композицию с “простых” компонентов, а другие подходы композиции используйте по мере необходимости.
Также стоит отметить про принцип Единый Уровень Абстракции (Single Level of Abstraction).
https://www.developerway.com/posts/components-composition-how-to-get-it-right
При разработке приложения на React возникает сложность в разделении компонентов и их правильной композиции между собой. Некоторые разработчики не разделяют компонент на более мелкие и получают большой компонент-монолит, который в дальнейшем сложно поддерживать. Также некоторые разработчики начинают разделять компонент на более мелкие подкомпоненты слишком рано, что приводит к оверинженирингу и сложно поддерживаемому коду.
В React есть несколько подходов к композиции компонентов. Есть “простые” компоненты:
const Button = ({ noscript, onClick }) => <button onClick={onClick}>{noscript}</button>;
И компоненты контейнеры:
const Button = ({ children, onClick }) => <button onClick={onClick}>{children}</button>;
У компонента контейнера вместо пропса noscript проп children. Это различие позволяет более гибко использовать компонент контейнер и передавать в children любые элементы, при этом синтаксис выглядит как использование обычного HTML тега.
Можно определить следующие правила для декомпозиции компонента:
- Начинайте реализацию “сверху вниз”. Если делать “снизу вверх”, т.е. сначала создавать небольшие переиспользуемые компоненты, то возможно у вас получится компонент со слишком сложным API и будет отсутствовать половина нужного функционала.
- Создавайте подкомпонент только тогда, когда в этом есть необходимость. Одно из возможных причин, когда компонент нужно декомпозировать – это его размер.
- Начинайте композицию с “простых” компонентов, а другие подходы композиции используйте по мере необходимости.
Также стоит отметить про принцип Единый Уровень Абстракции (Single Level of Abstraction).
https://www.developerway.com/posts/components-composition-how-to-get-it-right
Medium
Coding React components: Single Level of Abstraction
Learn how to make your React components easier to understand by following the Single Level of Abstraction principle.
👍6🔥6👎1
Упускаемый из виду фактор оптимизации производительности в React
Когда идет речь о производительности компонента, необходимо учитывать его положение в дереве компонентов.
Многие люди иногда любят искать простые ответы на проблемы, с которыми они сталкиваются. Для большинства проблем довольно легко прийти к общему решению, но в этом случае мы не учитываем крайние случаи. В случае с производительностью React приложений, одним из этих крайних случаев является позиция компонента в дереве компонентов.
Наверняка вы знаете поведение рендера при использовании контекста: при изменении значения контекста компонент-потребитель будет отрендерен заново (проверка происходит по ссылке).
В примере выше при каждом повторном рендере Parent будет происходить повторный рендер потребителей контекста, т.к. изменилась ссылка на значение. Самый легкий способ это исправить - это обернуть значение в useMemo. Однако это избыточно для компонентов в верху дерева компонентов. В примере выше Parent находится в самом верху дерева и выше него нет других компонентов, которые могли бы спровоцировать повторный рендер. Таким образом использование функции useMemo в примере выше бесполезна.
https://www.zhenghao.io/posts/top-level-perf
Когда идет речь о производительности компонента, необходимо учитывать его положение в дереве компонентов.
Многие люди иногда любят искать простые ответы на проблемы, с которыми они сталкиваются. Для большинства проблем довольно легко прийти к общему решению, но в этом случае мы не учитываем крайние случаи. В случае с производительностью React приложений, одним из этих крайних случаев является позиция компонента в дереве компонентов.
Наверняка вы знаете поведение рендера при использовании контекста: при изменении значения контекста компонент-потребитель будет отрендерен заново (проверка происходит по ссылке).
function App() {
return (
<Parent>
<Child />
</Parent>
);
}
function Parent({children}) {
const [stateA, dispatchA] = useReducer(reducerA, initialStateA);
return (
<div className="parent">
<Context.Provider value={[stateA, dispatchA]}>{children}</Context.Provider>
</div>
);
}
В примере выше при каждом повторном рендере Parent будет происходить повторный рендер потребителей контекста, т.к. изменилась ссылка на значение. Самый легкий способ это исправить - это обернуть значение в useMemo. Однако это избыточно для компонентов в верху дерева компонентов. В примере выше Parent находится в самом верху дерева и выше него нет других компонентов, которые могли бы спровоцировать повторный рендер. Таким образом использование функции useMemo в примере выше бесполезна.
https://www.zhenghao.io/posts/top-level-perf
zhenghao.io
an overlooked factor for performance optimization in React
when talking about performance, remember to consider the component’s position in the tree.
👍6
История Next.js
На канале uidotdev вышло видео про Next.js, в котором рассказывают про историю появления этого фреймворка и какие проблемы он решает. Также, в видео есть немного про историю JavaScript.
https://www.youtube.com/watch?v=BILxV_vrZO0
На канале uidotdev вышло видео про Next.js, в котором рассказывают про историю появления этого фреймворка и какие проблемы он решает. Также, в видео есть немного про историю JavaScript.
https://www.youtube.com/watch?v=BILxV_vrZO0
YouTube
The Story of Next.js
This is the story of how Next.js took over the world.
👍5
Производительность фронтенда: большое приложение на реактивном SSR-топливе
Виталий Старов рассказывает как устроен серверный рендеринг в большом приложение. В статье описан путь пользователя при загрузке страницы сайта, какие процессы стоят за этим действием. Статья хороша тем, что объясняется выбор определенных библиотек.
Одна из проблем в серверном рендеринге – стили. Если использовать CSS-in-JS, то могут возникнуть проблемы при гидратации. Например, JSS наиболее чувствителен к ситуации, когда на сервере и в браузере компонент был отрендерен по разному, в этом случае стили могут сломаться.
https://habr.com/ru/company/superjob/blog/660681/
Виталий Старов рассказывает как устроен серверный рендеринг в большом приложение. В статье описан путь пользователя при загрузке страницы сайта, какие процессы стоят за этим действием. Статья хороша тем, что объясняется выбор определенных библиотек.
Одна из проблем в серверном рендеринге – стили. Если использовать CSS-in-JS, то могут возникнуть проблемы при гидратации. Например, JSS наиболее чувствителен к ситуации, когда на сервере и в браузере компонент был отрендерен по разному, в этом случае стили могут сломаться.
https://habr.com/ru/company/superjob/blog/660681/
Хабр
Производительность фронтенда: большое приложение на реактивном SSR-топливе
Каждый день сайтом SuperJob пользуется более миллиона людей. Как построить архитектуру фронта, чтобы приложение загружалось быстро и при этом выполняло требования поисковой оптимизации? Как мы можем...
👍3
Новый текстовый редактор для React – Lexical
Lexical – это новая библиотека для создания текстового редактора с упором на надежность, доступность и производительность. Ядро библиотеки весит всего 22КБ, а нужные плагины для работы редактора можно загружать через lazy load по мере их использования пользователем.
Библиотека не привязана к какому-то конкретному фреймворку и даже к платформе. В планах есть реализация API для iOS. В первую очередь был выбран web и есть официальные биндинги для React.
Внутреннее состояние редактора представляет из себя дерево узлов и объект выбора. Узлы представляют собой основную концепцию в Lexical. Они не только нужны для рендера, но также представляют базовую модель данных для хранения в редакторе для истории. Узлы в редакторе расширяемы, и на основе существующих можно создавать свои кастомные узлы.
Пример компонента:
https://lexical.dev/
Lexical – это новая библиотека для создания текстового редактора с упором на надежность, доступность и производительность. Ядро библиотеки весит всего 22КБ, а нужные плагины для работы редактора можно загружать через lazy load по мере их использования пользователем.
Библиотека не привязана к какому-то конкретному фреймворку и даже к платформе. В планах есть реализация API для iOS. В первую очередь был выбран web и есть официальные биндинги для React.
Внутреннее состояние редактора представляет из себя дерево узлов и объект выбора. Узлы представляют собой основную концепцию в Lexical. Они не только нужны для рендера, но также представляют базовую модель данных для хранения в редакторе для истории. Узлы в редакторе расширяемы, и на основе существующих можно создавать свои кастомные узлы.
Пример компонента:
const editorConfig = {
// The editor theme
theme: ExampleTheme,
// Handling of errors during update
onError(error) {
throw error;
},
// Any custom nodes go here
nodes: [
HeadingNode,
ListNode,
ListItemNode,
QuoteNode,
CodeNode,
CodeHighlightNode,
TableNode,
TableCellNode,
TableRowNode,
AutoLinkNode,
LinkNode
]
};
export default function Editor() {
return (
<LexicalComposer initialConfig={editorConfig}>
<div className="editor-container">
<ToolbarPlugin />
<div className="editor-inner">
<RichTextPlugin
contentEditable={<ContentEditable className="editor-input" />}
placeholder={<Placeholder />}
/>
<HistoryPlugin />
<TreeViewPlugin />
<AutoFocusPlugin />
<CodeHighlightPlugin />
<ListPlugin />
<LinkPlugin />
<AutoLinkPlugin />
<ListMaxIndentLevelPlugin maxDepth={7} />
<LexicalMarkdownShortcutPlugin />
</div>
</div>
</LexicalComposer>
);
}
https://lexical.dev/
🔥6👍1
Хуки, зависимости и устаревшие замыкания
Замыкание очень часто используется в функциональных компонентах, когда внутри компонента объявляется функция и в ней используются пропсы компонента:
Замыкание- это когда функция может взаимодействовать с окружающими переменными. Само замыкание создается каждый раз, когда создается функция, в момент создания функции.
В функциональных компонентах замыкание работает как надо, при каждом рендере компонента объявленные внутри компонента функции создаются заново и получают в свое окружение новые пропсы.
Чаще всего это не вызывает никаких проблем, однако, если понадобится мемоизация функции, то нужно будет оборачивать функцию в useCallback.
При работе с хуками рекомендуется использовать линтер
https://tkdodo.eu/blog/hooks-dependencies-and-stale-closures
Замыкание очень часто используется в функциональных компонентах, когда внутри компонента объявляется функция и в ней используются пропсы компонента:
function Counter({ count }) {
const logCount = () => {
// переменной count берется из внешнего окружения
console.log('count', count)
}
return <button onClick={logCount}>Show me the count</button>
}
Замыкание- это когда функция может взаимодействовать с окружающими переменными. Само замыкание создается каждый раз, когда создается функция, в момент создания функции.
В функциональных компонентах замыкание работает как надо, при каждом рендере компонента объявленные внутри компонента функции создаются заново и получают в свое окружение новые пропсы.
Чаще всего это не вызывает никаких проблем, однако, если понадобится мемоизация функции, то нужно будет оборачивать функцию в useCallback.
При работе с хуками рекомендуется использовать линтер
react-hooks/exhaustive-deps, который подсвечивает неопределенные зависимости для хука useCallback. Если игнорировать список зависимостей useCallback, то используемые внутри него переменные компонента будут устаревшими. https://tkdodo.eu/blog/hooks-dependencies-and-stale-closures
tkdodo.eu
Hooks, Dependencies and Stale Closures
Let's demystify what stale closures are in combination with react hooks with the help of the analogy of taking a photo ...
👍7
HolyJS — конференция для JavaScript-разработчиков от JUG Ru Group, в формате online+offline
Online-часть: 8–10 июня.
Offline-день: 23 июня.
В online вас ждут выступления, посвященные трендам и новым технологиям, обмен опытом и общение в чатах.
На offline-дне в Санкт-Петербурге можно вживую послушать спикеров, лично познакомиться с коллегами и потусоваться у стендов партнеров.
В программе:
– Каким бывает легаси во фронтенде, как с ним справляться и не допускать его появления.
– Что такое proposal Wasm GC, почему его так долго делают и какой путь прошли движки за 2 года экспериментов.
– Как построить дизайн-систему для продукта с 20-миллионной аудиторией, огромной кодовой базой и массой поверхностей.
– Что такое сложность для человеческого мозга и как эти знания помогают писать более понятный код.
Для подписчиков канала организаторы сделали промокод, который поможет вам купить персональный билет со скидкой:
Билеты, подробности и первая программа— на сайте.
Online-часть: 8–10 июня.
Offline-день: 23 июня.
В online вас ждут выступления, посвященные трендам и новым технологиям, обмен опытом и общение в чатах.
На offline-дне в Санкт-Петербурге можно вживую послушать спикеров, лично познакомиться с коллегами и потусоваться у стендов партнеров.
В программе:
– Каким бывает легаси во фронтенде, как с ним справляться и не допускать его появления.
– Что такое proposal Wasm GC, почему его так долго делают и какой путь прошли движки за 2 года экспериментов.
– Как построить дизайн-систему для продукта с 20-миллионной аудиторией, огромной кодовой базой и массой поверхностей.
– Что такое сложность для человеческого мозга и как эти знания помогают писать более понятный код.
Для подписчиков канала организаторы сделали промокод, который поможет вам купить персональный билет со скидкой:
reactnotes2022JRGpcБилеты, подробности и первая программа— на сайте.
👍3❤1
Вышло обновление React 18.1
Спустя месяц после релиза вышло минорное обновление React 18.1.
Среди основных изменений:
- тег <noscript> больше не ругается на react-dom/client
- renderToPipeableStream стал в ~20 раз быстрее
- исправлено двойное срабатывание componentWillUnmount в Suspense
- исправлена ошибка бесконечного ререндера компонента в useDeferredValue
- исправлены различные ошибки гидратации
https://github.com/facebook/react/blob/main/CHANGELOG.md#1810-april-26-2022
Спустя месяц после релиза вышло минорное обновление React 18.1.
Среди основных изменений:
- тег <noscript> больше не ругается на react-dom/client
- renderToPipeableStream стал в ~20 раз быстрее
- исправлено двойное срабатывание componentWillUnmount в Suspense
- исправлена ошибка бесконечного ререндера компонента в useDeferredValue
- исправлены различные ошибки гидратации
https://github.com/facebook/react/blob/main/CHANGELOG.md#1810-april-26-2022
GitHub
react/CHANGELOG.md at main · facebook/react
The library for web and native user interfaces. Contribute to facebook/react development by creating an account on GitHub.
🔥15
Как работает Virtual DOM в React
Как мы знаем, DOM- это древовидная структура, которая используется для отображения элементов на странице. Работа напрямую с DOM может быть достаточно дорогостоящим процессом, т.к. операции с DOM выполняются медленно. React работает не напрямую с браузерным DOM, а через Virtual DOM.
Virtual DOM – это древовидная структура объектов, которая хранится в памяти браузера и хранит элементы страницы. Задача Virtual DOM – определить, что изменилось с точки зрения содержимого элементов или структуры страницы и закоммитить все изменения в реальный DOM.
По своей сути Virtual DOM – это древовидная структура объектов FiberNode (а в целом это FiberTree). FiberNode представляет собой React элемент.
Компонент выше содержит четыре FiberNode: App, <article>, <h2>, <p>. Каждый FiberNode содержит ссылки на соседние FiberNode, родительский и дочерний. Рассмотрим основные свойства FiberNode, сопоставив их значения с примером выше:
-
-
-
В процессе рендера для того, чтобы узнать о необходимых изменениях, в каждом FiberNode есть свойство
https://indepth.dev/posts/1501/exploring-how-virtual-dom-is-implemented-in-react
Как мы знаем, DOM- это древовидная структура, которая используется для отображения элементов на странице. Работа напрямую с DOM может быть достаточно дорогостоящим процессом, т.к. операции с DOM выполняются медленно. React работает не напрямую с браузерным DOM, а через Virtual DOM.
Virtual DOM – это древовидная структура объектов, которая хранится в памяти браузера и хранит элементы страницы. Задача Virtual DOM – определить, что изменилось с точки зрения содержимого элементов или структуры страницы и закоммитить все изменения в реальный DOM.
По своей сути Virtual DOM – это древовидная структура объектов FiberNode (а в целом это FiberTree). FiberNode представляет собой React элемент.
function App () {
return (
<article>
<h2>Title</h2>
<p>Some content</p>
</article>
)
}
Компонент выше содержит четыре FiberNode: App, <article>, <h2>, <p>. Каждый FiberNode содержит ссылки на соседние FiberNode, родительский и дочерний. Рассмотрим основные свойства FiberNode, сопоставив их значения с примером выше:
-
child - дочерний элемент. AppFiberNode.child === ArticleFiberNode-
sibling - соседний элемент. H2FiberNode.sibling === PFiberNode-
return - родительский элемент. H2FiberNode.return === ArticleFiberNodeВ процессе рендера для того, чтобы узнать о необходимых изменениях, в каждом FiberNode есть свойство
alternate. В нем хранится ссылка на копию текущего FiberNode, который был закоммичен в DOM. В процессе рендера происходит сравнение текущего FiberNode и его копии в alternate, и, если они отличаются, то происходит коммит изменений. https://indepth.dev/posts/1501/exploring-how-virtual-dom-is-implemented-in-react
👍6❤2