Библиотека фронтендера | Frontend, JS, JavaScript, React.js, Angular.js, Vue.js
21.6K subscribers
2.88K photos
204 videos
47 files
5.18K links
Все самое полезное для фронтенда в одном канале.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/77178ed4

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a5b6884689c2151c820bb4
Download Telegram
😓 100vh съедает половину экрана на мобилках

Классика: делаешь height: 100vh для фуллскрин-секции, на десктопе всё ок, а на телефоне контент уезжает за экран и появляется скролл.

В чем причина:

Браузер считает 100vh по полной высоте экрана, включая скрывающиеся панели. Когда скроллишь — адресная строка прячется, высота viewport меняется, и блок начинает прыгать.

Раньше приходилось считать реальную высоту через JS — решение рабочее, но костыль.

🔤 Теперь есть нормальные CSS-единицы (с 2022 года):

dvh — динамическая высота, подстраивается при скролле

svh — учитывает адресную строку

lvh — без адресной строки, максимальная высота


Поддержка: iOS 15.4+, Chrome 108+, Safari 15.4+

Fallback:

Сначала указываем height: 100vh, а следом height: 100dvh — новые браузеры просто переопределят старое значение.

🐸 Библиотека фронтендера

#hotfix #css
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18🥰5❤‍🔥41
🔥 Props через 5 уровней — рефакторим через children

➡️ Проблема (1 картинка):

Передаём user через Dashboard и Sidebar, хотя они его не используют. Компоненты становятся «курьерами» для чужих данных.

➡️ Решение (2 картинка):

Используйте композицию через children — передавай данные напрямую туда, где они нужны.

Что это даёт:

🟡 Без prop drilling — данные идут напрямую к UserProfile
🟡 Dashboard и Sidebar становятся переиспользуемыми
🟡 Меньше связности, проще тестировать и поддерживать

Когда что использовать:

Композиция — данные нужны только конечному компоненту
Context API — данные нужны многим компонентам на разных уровнях (theme, auth, locale)

🐸 Библиотека фронтендера

#hotfix #react
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍42👏1🌚1
😓 Роутинг в SPA — боль

Классика: слушаем click, ставим preventDefault(), делаем history.pushState(), потом ловим popstate и рендерим контент.
Работает, но это куча бойлерплейта и расхождений между состоянием, URL и историей.

Почему так:

History API не создавался под SPA. Он не умеет централизованно управлять всеми типами навигации и не даёт понять, когда переход «завершён», чтобы безопасно менять UI и скролл.

🔤 Нормальное решение — Navigation API (эксперимент, Chrome 102+):

• navigate — единое событие для всех переходов
• event.intercept() — перехват и свой обработчик (загрузили данные, отрисовали, проверили доступ)
• event.scroll() — нативный скролл
• { committed, finished } — когда менять URL и когда переход реально завершён
• entries() и currentEntry — история как нормальные объекты со state


Fallback:

Если window.navigation нет, остаёмся на старом pushState.


if ('navigation' in window) {
navigation.addEventListener('navigate', (event) => {
if (shouldNotIntercept(event)) return;
const url = new URL(event.destination.url);

event.intercept({
async handler() {
renderSkeleton();
const html = await fetchPage(url.pathname);
render(html);
event.scroll();
},
});
});

const { committed, finished } = navigation.navigate('/profile');
committed.then(() => showLoading());
finished.finally(() => hideLoading());
}


📦 Поддержка:

Chromium 102+, Safari (новые версии), Firefox — пока нет.
API экспериментальный, используйте feature-detect.

📎 Официальная спецификация

🐸 Библиотека фронтендера

#hotfix #js
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰53🔥1
🚀 AbortController — как правильно отменять запросы

➡️ Проблема (1 картинка):

Пользователь быстро переключает вкладки или вводит текст в поиске. Старые запросы продолжают работать и могут перезаписать актуальные данные.

➡️ Решение (2 картинка):

Отменяйте предыдущие запросы через AbortController

Что это даёт:

🟢 Нет race condition — обновляется только последний запрос

🟢 Браузер действительно отменяет запрос на уровне сети

🟢 Код без лишних флагов вроде isCancelled

🟢 Работает с API, которые поддерживают AbortSignal (fetch, Axios ≥0.22, React Query)

Когда применять:

— Автодополнение и live-поиск
— Переключение вкладок и фильтров
— Отмена запросов при размонтировании компонента
— Повторные запросы в useEffect при изменении зависимостей

⚠️ Важные детали:

controller.abort() можно вызывать многократно — это безопасно
Отмена происходит на стороне клиента — запрос может дойти до сервера
После abort() новые запросы с тем же controller не сработают (создавайте новый)

Поддержка:

🟣 Fetch API — нативно
🟣 Axios ≥ 0.22 — через signal
🟣 React Query — через queryFn

🐸 Библиотека фронтендера

#hotfix #react
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🥰43
🔥 Next.js 16: Server Components вместо useEffect

Проблема (1 картинка):

'use client' + useEffect + fetch — данные загружаются на клиенте. Медленно, нужны loading states вручную, нет кэша.

Решение (2 картинка):

Server Components — просто async/await в компоненте. Данные на сервере, кэширование через next: { revalidate }.

Что это даёт:

🟢 Быстрее — данные приходят с HTML
🟢 Меньше JS — 0 байт на клиенте для фетчинга
🟢 Умный кэш — revalidate: 60 = обновление раз в минуту
🟢 Проще код — никаких useState/useEffect

Бонус-паттерны:

Параллельный фетчинг:


const [posts, users] = await Promise.all([
fetch('/api/posts'),
fetch('/api/users')
])


Server Actions:


export async function createPost(data) {
'use server'
await db.posts.create(data)
revalidatePath('/posts') // Инвалидация кэша
}


Streaming:


<Suspense fallback={<Skeleton />}>
<Posts />
</Suspense>


⚠️ Fetch больше не кэшируется по умолчанию. Явно указывайте next: { revalidate } или cache: 'force-cache'.

🐸 Библиотека фронтендера

#hotfix #react
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰8🔥4🥱32
📦 Container Queries — респонсив по контейнеру, а не по экрану

Проблема: карточка в гриде, сайдбаре и модалке выглядит по-разному. Media queries не помогут — они смотрят на viewport.

ℹ️ Кейсы:

— Виджеты в дашбордах
— UI-киты с гибкими компонентами
— Карточки в разных местах

🟡 Юниты: cqi, cqw — как vw, но для контейнера

⚙️ Поддержка: Chrome 105+, Safari 16+, Firefox 110+

🐸 Библиотека фронтендера

#hotfix #css
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥1
⚛️ React: избавляемся от вложенных условий в JSX

Глубокие тернарные операторы быстро превращают JSX в нечитаемый код. Более понятный подход — ранние возвраты и предсказуемая структура рендера.

⚠️ Важное правило Hooks

Все хуки должны вызываться на верхнем уровне компонента — до любых return и условных конструкций.

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

// Ошибка: хук после return
function Component({ data }) {
if (!data) return null;
const [value] = useState(data); // Хук вызван условно!
}

// Правильно: хуки перед return
function Component({ data }) {
const [value] = useState(data);
if (!data) return null;
}


Ранние возвраты полностью безопасны, если хуки вызываются до любых условий.

Альтернатива: объектный маппинг

Подходит для компонентов с большим количеством состояний:

const STATE_COMPONENTS = {
loading: Spinner,
error: Error,
success: Content,
empty: Empty
};

function DataView({ status, ...props }) {
const Component = STATE_COMPONENTS[status];
return Component ? <Component {...props} /> : null;
}

Важно: храните компоненты, а не JSX-элементы, чтобы свободно передавать пропсы.

➡️ Когда что использовать:

⚪️ Early Returns — оптимальны в большинстве случаев (loading / error / success).

⚪️ Объектный маппинг — подходит, когда состояний много и они определяются строковым статусом: этапы процессов, статусы заказов, типы уведомлений, шаги визардов.

💡 Начинайте с early returns — это самый простой и понятный вариант. Переходите на маппинг только тогда, когда это действительно упрощает код.

🐸 Библиотека фронтендера

#hotfix #react
Please open Telegram to view this post
VIEW IN TELEGRAM
👍75🥰3
Grid vs Flex для центрирования — как делать правильно

Когда нужен простой и предсказуемый центр по обеим осям — Grid справляется быстрее и чище, чем Flex.

➡️ Когда Grid — точное решение:

• модальные окна
• лоадеры и спиннеры
• empty states
• hero-блоки
• карточки с иконками и коротким текстом


Любой статичный компонент, где центр — ключевая точка внимания.

💡 Полезный приём

place-items — это шорткат для align-items + justify-items.

Можно настраивать оси раздельно:


.container {
display: grid;
place-items: start center; /* вертикаль | горизонталь */
}


➡️ Когда Flex всё ещё лучше:

Flex выигрывает в динамических сценариях:
• несколько элементов в строке
• space-between / space-around
• адаптивный wrap
• навигация, списки, карточки в ряду


Если нужно распределить несколько элементов, а не центрировать один — выбирайте Flex.

🌐 Поддержка: Chrome 59+, Firefox 45+, Safari 11+, Edge 79+

🐸 Библиотека фронтендера

#hotfix #css
Please open Telegram to view this post
VIEW IN TELEGRAM
👍63🥰2