progway — программирование, IT
2.6K subscribers
25 photos
1 video
246 links
Чат: @prog_way_chat

Разборы вопросов и задач с собеседований, мысли, полезные материалы и просто вещи, что мне интересны из мира IT

Полезности и навигация в закрепе

По всем вопросам: @denisputnov
Download Telegram
Связываем React и localStorage через useSyncExternalStore

Как согласовать изменение состояния в реакте и поля в localStorage? До недавнего времени самым простым вариантом было создать контекст с внутренним React состоянием и обрабатывать всё взаимодействие с localStorage через него — вариант рабочий, но далеко не идеален: легко напороться на ререндеры, много кода писать нужно ну и вот это вот всё

Также можно обработать какое-то не-реактовое значение через комбинацию useState + useEffect, но это ещё менее надёжно, ведь браузерные значения могут меняться и без уведомления реакта, и, соответственно, без ререндера

Красиво в одной из статей на хабре описали:

Для работы с состоянием в React используются хуки useState и useReducer, но они не умеют работать с состоянием, которое "живет" за пределами React, поскольку в один момент времени доступна только одна версия внешнего состояния.

Значения внешнего состояния могут меняться со временем без ведома React, что может приводить к таким проблемам, как отображение двух разных значений для одних и тех же данных.

Статья: https://habr.com/ru/companies/timeweb/articles/720136/


Но не так давно в 18 версию React добавили хук useSyncExternalStore, который такую задачу решает намного изящнее

Многие скипнули его и даже не знают зачем он нужен, что, в целом, достаточно ожидаемо, ведь даже команда разработчиков позиционировала его больше как хук для разработчиков библиотек, а мы тут далеко не все пишем свои либы

Короче, что это за хук вообще? Очень просто — этот хук нужен для более глубокой интеграции внешних хранилищ в модель React. Говоря проще — хук нужен для того, чтобы триггерить рендер из внешних хранилищ, а не только через setState функции

Как раз этот хук и поможет нам интегрироваться с localStorage сильно проще и безопаснее. Тут localStorage в понятие внешнего хранилища ложится просто шикарно

На коленке код будет выглядеть примерно так:

const useLocalStorageState = (key: string, defaultValue?: string) => {
const subscribe = (listener: () => void) => {
window.addEventListener("update-local-storage", listener);
return () => void window.removeEventListener("update-local-storage", listener);
};

const getSnapshot = () => localStorage.getItem(key) ?? defaultValue;

const store = useSyncExternalStore(subscribe, getSnapshot);

const updateStore = (newValue: string) => {
localStorage.setItem(key, newValue);
window.dispatchEvent(new StorageEvent("update-local-storage", { key, newValue }));
};

return [store, updateStore] as const;
};


В чём тут идея:
1. При вызове updateStore будем помимо изменения значения в localStorage диспатчить на window ещё и StorageEvent с ключом, например, "update-local-storage"
2. В функции подписки subscribe объясним когда нужно вызывать getSnapshot для получения актуального состояния из внешнего хранилища и когда от его прослушивания нужно отписаться. Можно воспринимать как эффект

Использовать будем как обычный useState:
const [name, setName] = useLocalStorageState("name", "progway");


Теперь хук при вызове с одним и тем же ключом к localStorage (name в примере выше) будет обновлять все зависимые компоненты при регистрации события "update-local-storage" на window

Используя тот же подход, можно реализовать порой очень полезные хуки useMediaQuery, useWindowSize и другие. О первых двух можно прочитать в статье от Timeweb Cloud

Спасибо за прочтение, это важно для меня ❤️

@prog_way_blogчат#web #javascript #theory #data #code #react
Please open Telegram to view this post
VIEW IN TELEGRAM
28👍11🔥6🐳2
Флоу рендеринга компонента в React

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

➡️При маунте порядок следующий:

1. Рендер на основе изначальных значений состояний
2. useInsertionEffect
3. Создание DOM
4. Прикрепление ссылок на ноды (ref)
5. useLayoutEffect
6. useEffect

➡️При апдейте компонента:

1. Рендер на основе новых значений состояний
2. Обновление DOM
3. useInsertionEffect
4. Прикрепление ссылок на ноды (ref)
5. useLayoutEffect
6. useEffect

📎Решил вынести её в канал, потому что сам прям недавно сталкивался с этим на рабочем проекте и подумал, что это тоже кому-то может быть полезно

Ну и не реклама, а реально рекомендация — на эту тему хочу поделиться видео Аюба Бегимкулова о нестандартном применении useInsertionEffect. Там он более подробно рассказывает почему порядок именно такой и в целом чуть более подробно раскрывает тему рендера с примерами в коде

Спасибо за прочтение, это важно для меня ❤️

@prog_way_blogчат#web #theory #react
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥34🐳511👍1
Верстка писем — это боль? или нет..?

Если вы думали, что адаптивная верстка для всех браузеров — это сложно, попробуйте сверстать email, который одинаково выглядит в Gmail, Outlook, Yahoo и десятках других почтовых клиентов...


Вёрстка письма — это крайне специфичное занятие, при котором нет возможности использовать добрую половину, если не больше, возможностей HTML и CSS

Почтовые движки настолько старые, что многие из них до сих пор требуют верстки с использованием таблиц, прямо как в 90-х. Но гораздо интереснее вопрос — почему получилось именно так? Я бы выделил пару причин:

➡️ Что и так понятно, причина историческая

Вёрстка письма — задача часто тривиальная. Вот многие и не заморачиваются с обновлением движков, так как это не дает какой-то бизнес выгоды. Нет абсолютно никакой разницы между вёрсткой письма для отправки PIN-кода для входа на таблицах или на флексах

➡️ Безопасность

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

@font-face { src: url(...) }
background-image: url(...)
list-style-image: url(...)

<form action="https://.../steal.php" method="get">


И ещё куча других примеров — везде так или иначе наше письмо отправляет какой-то запрос. А это уже опасно тем, что открывает кучу возможностей для слежки за пользователем. Например, можно узнать реальный IP пользователя просто при открытии письма (открытие письма → запрос картинки → трекинг IP)

Также, например, запрещён position:fixed, потому что позволяет фиксировать элементы на экране, что можно использовать для фишинга. Например, можно зафиксировать модалку поверх письма с призывом ввести пароль, и она будет выглядеть как часть интерфейса почтового клиента

Но самое главное, что всё реально развивается и стало лучше!


— Outlook теперь рендерит письма на движке от Edge, а не от Microsoft Word (блин, да! до 2022 года письма реально рендерились на основе... ворда! )
— почти все почтовые клиенты научились понимать <div /> 😎
— много где появилась поддержка медиа запросов
— ну и много чего ещё

А самое главное, что появились крутые инструменты для вёрстки писем, которые из коробки закрывают много проблем — когда-то относительно давно появился MJML и сделал небольшую революцию, а в последние годы так и вовсе очень сильно хайпят react-email или vue-email

Мне недавно довелось сверстать десяток писем на react-email и с уверенностью могу сказать, что это было совсем-совсем не больно:
— тут тебе и tailwind
— и аля аналог storybook для шаблонов
— кастомные шрифты
— куча шаблонов и примеров кода
— поддержка markdown для текстов
— куча фиксов для почтовых клиентов...

И
всё это чудо в удобной обёртке из коробки с поддержкой компонентного подхода без смс и даже без регистрации

Как по мне, в современных реалиях верстать письма стало в разы легче, за что большое спасибо всему комьюнити. Если вдруг ранее вы обходили стороной вёрстку писем, загляните. Это тоже по-своему интересно

Ну и react-email тоже рекомендую, приятный инструмент

Спасибо за прочтение, это важно для меня ❤️

@prog_way_blogчат#useful #web #react
Please open Telegram to view this post
VIEW IN TELEGRAM
👍326🔥6🐳2🤔1