fa
Feedback
React

React

رفتن به کانال در Telegram

Подборки по React js и все что с ним связано. По всем вопросам @evgenycarter

نمایش بیشتر
2 733
مشترکین
+124 ساعت
-57 روز
-1030 روز
آرشیو پست ها
React
2 732
✍️ @React_lib
✍️ @React_lib

React
2 732
Выжимка самого полезного о библиотеке Motion для React из англоязычной документации Когда я начал разбираться с Motion для Re
Выжимка самого полезного о библиотеке Motion для React из англоязычной документации Когда я начал разбираться с Motion для React, то оказалось, что свежих обзорных статей почти нет — нашёл только несколько старых постов про framer-motion. Поэтому я решил написать свой обзор: перевёл и разобрал документацию (ссылки в конце), попробовал библиотеку в деле и собрал всё в одном месте. В статье есть примеры кода, GIF-анимации и описание хуков, которых, по моему личному мнению, достаточно, чтобы понять Motion, и, возможно, попробовать его руками, сэкономив время на чтении документации. https://habr.com/ru/companies/alfa/articles/942624/ ✍️ @React_lib

React
2 732
Формы без боли: react-hook-form + zod = схема в центре, минимум ререндеров Сейчас покажу, как я собираю формы так, чтобы вали
Формы без боли: react-hook-form + zod = схема в центре, минимум ререндеров Сейчас покажу, как я собираю формы так, чтобы валидация была в одном месте, а компоненты не прыгали от каждого ввода. 1) Схема — источник правды

import { z } from 'zod';

export const userSchema = z.object({
  email: z.string().email(),
  age: z.number().int().min(18),
  newsletter: z.boolean().default(false),
});
export type UserForm = z.infer<typeof userSchema>;
2) Инициализация формы с резолвером

import { useForm, FormProvider } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';

const UserForm = ({ initial }: { initial?: Partial<UserForm> }) => {
  const methods = useForm<UserForm>({
    resolver: zodResolver(userSchema),
    defaultValues: { newsletter: false, ...initial },
    mode: 'onChange', // мгновенная подсветка ошибок
  });

  const { handleSubmit, formState: { isSubmitting, errors } } = methods;

  const onSubmit = async (data: UserForm) => {
    // маппим серверные ошибки обратно в форму при необходимости
    // setError('email', { type: 'server', message: 'уже занято' })
    await api.saveUser(data);
  };

  return (
    <FormProvider {...methods}>
      <form onSubmit={handleSubmit(onSubmit)}>
        <Input name="email" label="Email" />
        <NumberInput name="age" label="Возраст" />
        <Checkbox name="newsletter" label="Подписаться" />
        {errors.root && <p className="error">{errors.root.message}</p>}
        <button disabled={isSubmitting}>Сохранить</button>
      </form>
    </FormProvider>
  );
};
3) Поля - через контекст, с мемоизацией

import { useFormContext, Controller } from 'react-hook-form';

// Простой контролируемый инпут с минимальными ререндерами
export const Input = React.memo(({ name, label }: { name: string; label: string }) => {
  const { register, formState: { errors } } = useFormContext();
  return (
    <label>
      {label}
      <input {...register(name)} />
      {errors[name] && <span className="error">{String(errors[name]?.message)}</span>}
    </label>
  );
});

// Пример для нестандартного компонента через Controller
export const NumberInput = React.memo(({ name, label }: { name: string; label: string }) => {
  const { control, formState: { errors } } = useFormContext();
  return (
    <label>
      {label}
      <Controller
        control={control}
        name={name}
        render={({ field }) => <input type="number" {...field} />}
      />
      {errors[name] && <span className="error">{String(errors[name]?.message)}</span>}
    </label>
  );
});
4) Динамические списки - useFieldArray

const { control } = useFormContext();
const { fields, append, remove } = useFieldArray({ control, name: 'phones' });
Храните массивы в форме, рендерите по fields, добавляйте/удаляйте кнопками - ререндерится только нужный участок. 5) Практические советы - Включайте DevTools формы только в dev. - Ошибки сервера маппьте через setError, а не кидайте alert. - При редактировании сущности меняйте key формы (<form key={user.id}>) — проще, чем делать reset в куче мест. - Дорогие поля оборачивайте в React.memo, а вычисления — в useMemo. ✍️ @React_lib

React
2 732
Почему ваш useEffect лишний (и что вместо него) Сейчас покажу 6 типичных случаев, где useEffect не нужен и только плодит баги
Почему ваш useEffect лишний (и что вместо него) Сейчас покажу 6 типичных случаев, где useEffect не нужен и только плодит баги и лишние рендеры. Дам короткие «до/после». 1. Вычисляемое из пропсов/стейта ❌ Плохо

const [fullName, setFullName] = useState('');
useEffect(() => { setFullName(`${user.first} ${user.last}`); }, [user]);
✅ Хорошо

const fullName = `${user.first} ${user.last}`;
2. Фильтрация/сортировка списка ❌ Плохо

const [filtered, setFiltered] = useState<Item[]>([]);
useEffect(() => { setFiltered(items.filter(byQuery(query))); }, [items, query]);
✅ Хорошо

const filtered = useMemo(() => items.filter(byQuery(query)), [items, query]);
3. Счётчики/таймеры для UI ❌ Плохо — пишут в стейт каждую секунду, лишний рендер ✅ Лучше — храните в useRef, рендерите только когда нужно показать новое число:

const tickRef = useRef(0);
useEffect(() => {
  const id = setInterval(() => { tickRef.current++; }, 1000);
  return () => clearInterval(id);
}, []);
// Когда надо отрисовать — дерните setState из контролируемой точки.
4. Синхронизация формы с данными ❌ Плохо — «заливают» в стейт через эффект ✅ Лучше — передавайте значения как defaultValue/values в форму или используйте «ключ» для ремонта формы:

<form key={user.id}>...</form>
5. Запросы данных ❌ Плохо — «сами» тащим fetch в эффект, пишем кэш, статус, отмену ✅ Лучше — вынесите в data-layer (например, TanStack Query) или хотя бы в отдельный хук с кэшем и отменой. 6. События окна/документа Если обработчик не использует реактивные данные — храните его в useRef и вешайте один раз. Если использует — чаще всего достаточно мемоизировать колбэк и вешать/снимать один раз.

const handlerRef = useRef<(e: KeyboardEvent) => void>(() => {});
handlerRef.current = (e) => { /* читаем актуальные значения из замыканий/рефов */ };

useEffect(() => {
  const onKey = (e: KeyboardEvent) => handlerRef.current(e);
  window.addEventListener('keydown', onKey);
  return () => window.removeEventListener('keydown', onKey);
}, []);
Мини-чеклист «нужен ли тут эффект?» - Это побочный эффект вне React (I/O, подписка, таймер, манипуляция DOM)? → Да — useEffect. - Это чистое вычисление на основе пропсов/стейта? → Нет эффекта, используем выражение/useMemo. - Можно ли пересчитать при рендере без записи в стейт? → Делайте это. - Будет ли этот эффект легко зафлапать гонками? → Пересмотрите дизайн. ✍️ @React_lib

React
2 732
Динамический импорт компонентов в React. Часто в приложении мы грузим сразу всё, даже то, что пользователю может и не понадоб
Динамический импорт компонентов в React. Часто в приложении мы грузим сразу всё, даже то, что пользователю может и не понадобиться. Например, модальные окна, сложные графики, админские панели. Это увеличивает бандл и замедляет загрузку. Решение простое — использовать React.lazy и Suspense:

import { Suspense, lazy } from "react";

const Chart = lazy(() => import("./Chart"));

function Dashboard() {
  return (
    <div>
      <h1>Статистика</h1>
      <Suspense fallback={<p>Загрузка графика...</p>}>
        <Chart />
      </Suspense>
    </div>
  );
}
Теперь график подгрузится только тогда, когда реально нужен. ⚡ Это экономит мегабайты и ускоряет first paint приложения. 👉 Но будь аккуратен: динамический импорт хорошо работает для редко используемых частей. А если компонент нужен почти всегда — выгоды не будет. Я, например, почти всегда лениво загружаю модальные окна и тяжелые виджеты. А ты используешь React.lazy у себя в проекте? ✍️ @React_lib

React
2 732
🚀 С 25 по 30 августа пройдёт Podlodka React Crew #3 — сезон о паттернах и практиках фронтенда. В программе: 💡 Паттерны и по
🚀 С 25 по 30 августа пройдёт Podlodka React Crew #3 — сезон о паттернах и практиках фронтенда. В программе: 💡 Паттерны и подводные камни View Transition API в React (Николай Шабалин, СберЗдоровье) 🧠 Глубокое погружение в архитектуру React Hooks (Максим Никитин, Rocket Science) ⚙️ Разбор FSD 2.1 на практике, без догм (Лев Челядинов, FSD Core team) 📚Подготовка к архитектурному интервью для фронтендеров (Игорь Антонов, Т-Банк) 📐Layout-паттерны за пределами Flexbox и CSS Grid (Саша Илатовский, Albato) 🎯 Все темы прикладные, с практикой и кейсами. 🔗 Подробности и билеты P.S: Для подписчиков группы React скидка 500 р по промокоду react_crew_3_Osn1zQ

React
2 732
Сегодня хочу показать вам один из практичных паттернов в React - Container & Presentational Components. Очень часто мы мешаем бизнес-логику и UI в одном компоненте. Это делает код тяжелым для поддержки, особенно в больших проектах. ⚡️ Подход простой: - Container-компоненты отвечают за работу с данными: запросы к API, обработку состояния, вызовы хендлеров. - Presentational-компоненты - только за отображение. Они получают данные и колбэки через props и не думают о том, откуда эти данные пришли. Пример 👇

// Container
function UserContainer() {
  const [user, setUser] = React.useState(null);

  React.useEffect(() => {
    fetch("/api/user")
      .then(res => res.json())
      .then(setUser);
  }, []);

  return <UserProfile user={user} />;
}

// Presentational
function UserProfile({ user }) {
  if (!user) return <p>Загрузка...</p>;
  return <h2>{user.name}</h2>;
}
👉 Такой подход облегчает тестирование, переиспользование компонентов и уменьшает связность. А как вы пишете? Делите логику и UI или чаще держите все в одном компоненте? ✍️ @React_lib

React
2 732
Всем доброго вечера! Сегодня я хочу рассказать вам о проблеме, которая встречается почти у каждого React-разработчика - "эффект дрожания" интерфейса при условном рендеринге. Допустим, у вас есть компонент, который отображает список данных после загрузки. Пока данные подгружаются, вы показываете спиннер, а потом - сам список. Всё вроде нормально… но при переключении состояния верстка “прыгает”, элементы смещаются, и пользователь видит неприятный скачок. 💡 Как решить? Главная идея — зарезервировать место под контент заранее. Даже если мы показываем скелетон или спиннер, блок должен иметь такую же высоту, как и итоговый контент. Например:

{isLoading ? (
  <div style={{ height: 300 }}>
    <Spinner />
  </div>
) : (
  <List items={data} />
)}
А ещё лучше — использовать скелетон-загрузчик (skeleton loader). Он повторяет форму будущего контента, и благодаря этому переключение происходит плавно и без сдвигов. 📌 Совет: в UI-библиотеках вроде Material UI или Ant Design уже есть готовые скелетоны - просто используйте их вместо "чистого" спиннера. Пользователь не заметит перехода, и приложение будет казаться быстрее. А у вас бывает, что верстка дергается при смене состояния? Как вы это решаете? ✍️ @React_lib

React
2 732
🤩Хотите, чтобы ваши React-приложения не просто работали, а вызывали вау-эффект? Присоединяйтесь к открытому уроку «Анимируем
🤩Хотите, чтобы ваши React-приложения не просто работали, а вызывали вау-эффект? Присоединяйтесь к открытому уроку «Анимируем React: от нуля до вау-эффекта» 12 августа в 20:00 МСК. Мы покажем, как создать живые, отзывчивые интерфейсы с помощью библиотеки анимаций Framer Motion и API Intersection Observer. Разберём, как добавить современный UX без перегрузки сторонними библиотеками, чтобы каждый элемент интерфейса был динамичным и запоминающимся. Освойте практические подходы и техники, которые используют профессионалы для создания визуально выразительных интерфейсов. Получите знания, которые значительно улучшат ваш опыт в React. ⚡️Присоединяйтесь к открытому вебинару и получите скидку на курс «React.js Developer»: https://vk.cc/cOkYCL Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru

React
2 732
Как я ускоряю разработку с помощью React DevTools Сегодня хочу поделиться инструментом, без которого я уже не представляю раб
Как я ускоряю разработку с помощью React DevTools Сегодня хочу поделиться инструментом, без которого я уже не представляю работу — React DevTools. Многие его ставят "для галочки", но реально используют только для просмотра компонентов. А ведь он может сильно ускорить разработку, если выжать из него максимум. Вот что реально помогает: 1. Профайлер — если у вас страница перерисовывается дольше, чем хотелось бы, откройте вкладку Profiler. Там видно, какие компоненты рендерятся лишний раз и сколько это занимает времени. 2. Поиск по дереву компонентов — если проект большой, можно быстро найти нужный компонент прямо в DevTools (Cmd/Ctrl + F). 3. Редактирование пропсов на лету — в режиме разработчика можно менять пропсы и сразу видеть результат без пересборки проекта. 4. Highlight updates — включает подсветку обновляемых компонентов. Очень удобно, чтобы найти “лишние” рендеры. Если вы еще не используете хотя бы профайлер и подсветку рендеров — попробуйте. Уже через пару дней вы начнете понимать, где проект "проседает" и что можно оптимизировать. А вы часто заглядываете в Profiler или больше по старинке — console.log и догадки? 😄 ✍️ @React_lib

React
2 732
Возможно, вам не нужен useEffect (версия с ref‑колбэками) В React хук useEffect часто используют для выполнения кода после монтирования компонента: подписки, измерения DOM-элементов, вызовы API и т. д. Но в некоторых случаях — особенно когда нам нужно только получить доступ к DOM-элементуuseEffect оказывается избыточным. Что предлагают вместо useEffect? Ref-колбэки. Вместо того чтобы ждать монтирования и использовать useEffect, можно передать функции-колбэку ссылку (ref). Этот колбэк автоматически вызовется, когда элемент появится или исчезнет в DOM. Когда использовать? - Для измерения DOM (размеры, позиция). - Для инициализации библиотек, которые работают с элементом. - Для управления фокусом. Если нужно реагировать на изменения состояния или выполнять сложные сайд-эффекты — тогда useEffect остаётся правильным выбором. ✍️ @React_lib

React
2 732
💪 Хотите работать в финтехе? Освойте Solidity! 👉 Востребованное обучение для разработчиков с опытом программирования от год
💪 Хотите работать в финтехе? Освойте Solidity! 👉 Востребованное обучение для разработчиков с опытом программирования от года, которые хотят получить навыки написания кода и аудита безопасности, чтобы попасть в одну из самых перспективных и высокооплачиваемых сфер IT. Освойте разработку децентрализованных приложений на профессиональном уровне всего за 5 месяцев на онлайн-курсе «Solidity Developer» от OTUS! Забудьте о скучном обучении — здесь вас ждут настоящие челленджи и нестандартные практические решения. А еще крутые проекты для портфолио! 👉 Пройдите вступительные тест для оценки подходит ли вам курс: https://vk.cc/cNUydi 🎁 Получите welcome скидку для успешное прохождение теста. Подробности уточняйте у менеджера. Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

React
2 732
📊 Tremor — готовые React-компоненты для дашбордов. Tremor предлагает более 35 настраиваемых и доступных компонентов React дл
📊 Tremor — готовые React-компоненты для дашбордов. Tremor предлагает более 35 настраиваемых и доступных компонентов React для создания информационных панелей и современных веб-приложений. Создан на основе Tailwind CSS и Radix UI. https://github.com/tremorlabs/tremor ✍️ @React_lib

React
2 732
⚛️ Как я ускоряю загрузку React-приложения с помощью динамического импорта Сеqxfc покажу вам простой, но эффективный способ у
⚛️ Как я ускоряю загрузку React-приложения с помощью динамического импорта Сеqxfc покажу вам простой, но эффективный способ ускорить загрузку React-приложения — динамический импорт компонентов. Особенно это полезно для ленивой загрузки тяжёлых страниц или модалок, которые не нужны сразу при старте. Вот базовый пример:

import React, { Suspense } from 'react';

const LazyComponent = React.lazy(() => import('./HeavyComponent'));

function App() {
  return (
    <div>
      <h1>Главная страница</h1>
      <Suspense fallback={<div>Загрузка...</div>}>
        <LazyComponent />
      </Suspense>
    </div>
  );
}
🧠 Что происходит: - HeavyComponent не загружается сразу при запуске. - Он подгрузится только тогда, когда понадобится. - Это уменьшает размер первоначального бандла и ускоряет первый рендер. 📌 Совет: Используй ленивую загрузку для: - страниц внутри роутинга (React Router + lazy) - редко используемых компонентов (например, SettingsModal) - тяжёлых графиков, таблиц, дашбордов 🔥 Бонус: Если хочешь ещё тоньше контролировать загрузку, подключи React Loadable или @loadable/component, которые дают больше гибкости и SSR поддержку. А вы используете ленивую загрузку в своих проектах? Делитесь кейсами 👇 ✍️ @React_lib

React
2 732
⚡️Хотите научиться писать надежные тесты для React-приложений и улучшить свои навыки в тестировании? Присоединяйтесь к открыт
⚡️Хотите научиться писать надежные тесты для React-приложений и улучшить свои навыки в тестировании? Присоединяйтесь к открытому уроку «Тестирование React-приложений с помощью React Testing Library» 23 июля в 20:00 МСК! Разберем: - Основы React Testing Library (RTL): философию и ключевые принципы. - Разницу между RTL и Enzyme, и почему RTL — лучший выбор. - Как тестировать рендеринг, события, асинхронный код и кастомные хуки. Это отличная возможность перед стартом курса «React.js Developer» от OTUS. Все участники получат скидку на обучение и полезные материалы для дальнейшего изучения. 👉Регистрация открыта: https://vk.cc/cNTB9v Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576

React
2 732
Секреты React-разработки. Создай React-портфолио с нуля шаг за шагом 👉 Полный цикл разработки: от первой строки кода до деплоя 👉 Создаём современный и динамичный сайт на React 👉 Полное руководство (4 часа 42 минуты) Сегодня я собрал в одном видео весь процесс создания портфолио на React с нуля! 🎥 В этом выпуске мы пройдём все этапы: от вёрстки и компонентов до анимации, переключения тем и финального деплоя. 💡 Что вы узнаете в этом видео: 🔹 Разработка структуры портфолио: создаём секции Home, About, Skills, Services, Portfolio, Clients, Contact. 🔹 Работа с React-компонентами: используем useState, useEffect, props и массивы данных. 🔹 Добавление анимации с Motion: оживляем интерфейс и создаём плавные переходы. 🔹 Переключение тем (светлая/тёмная): реализуем через useState и сохраняем в LocalStorage. 🔹 Динамическое меню и кнопка "Вверх": улучшаем навигацию и пользовательский опыт. 🔹 Деплой на Netlify: публикуем проект и делаем его доступным онлайн. ⏱️ Таймкоды: 00:07 — Обзор проекта - что мы будем разрабатывать в React 00:35 — Настройка окружения перед началом работы в React 15:53 — Создаём структуру проекта и компоненты 25:10 — Импортируем и подключаем картинки в проект 31:09 — Создаём компонент Header с меню навигации 57:50 — Разрабатываем секцию Home в React 01:05:05 — Создаём секцию About с данными о разработчике 01:13:30 — Добавляем секцию Skills с анимацией и эффектами 01:31:01 — Переходим к блоку Work Experience: оформление и логика 01:36:02 — Создаём секцию Services: карточки услуг и стили 02:02:49 — Разрабатываем секцию Portfolio с проектами 02:19:29 — Добавляем блок Next Project для перелистывания работ 02:24:35 — Создаём секцию Our Clients с отзывами и логотипами 02:44:38 — Разрабатываем секцию Contact с формой обратной связи 02:58:10 — Исправляем баг: убираем скролл при открытии мобильного меню 03:01:57 — Добавляем плавное появление popup в секции Portfolio 03:04:10 — Создаём секцию Footer с контактами и ссылками 03:22:00 — Добавляем кнопку "Вверх" для удобной навигации 03:28:33 — Реализуем переключение тем (светлая/тёмная) с сохранением 03:38:51 — Анимация элементов с помощью библиотеки React Motion 03:43:56 — Разбираем работу Motion: ключевые атрибуты и настройки 03:45:22 — Выносим анимацию в отдельный файл для удобства 04:19:07 — Обзор будущих проектов, которые можно реализовать 04:37:53 — Финальный деплой проекта на Netlify 04:42:23 — Всем мира и добра! 🚀😊 источник ✍️ @React_lib

React
2 732
Правило ESLint для обнаружения избыточного состояния в React ✍️ @React_lib

React
2 732
🧠 Зачем нужен React Query и как он меняет подход к загрузке данных Привет! Сегодня я хочу рассказать вам о библиотеке, которая стала для меня must-have в любом проекте на React — React Query. Если вы всё ещё пишете useEffect + fetch + useState, чтобы загрузить данные, ловите инсайт: это можно делать проще и мощнее. Вот чем React Query реально помогает: ✅ Автоматический кеш: данные не перезагружаются каждый раз при переходе между страницами. ✅ Повторные запросы при восстановлении соединения или фокусе окна. ✅ Мутации (POST, PUT и т.д.) с оптимистичным обновлением UI. ✅ Умное управление состояниями: isLoading, isError, data, refetch — всё под рукой. ✅ Простая интеграция с TypeScript. Пример использования:

const { data, isLoading, error } = useQuery({
  queryKey: ['users'],
  queryFn: () => fetch('/api/users').then(res => res.json())
});
🔥 Всё, никакого useEffect! А самое крутое — когда ты добавляешь бесконечный скролл или пагинацию — React Query делает это почти без боли. Если ещё не пробовал — обязательно покрути. Это прям реальный буст продуктивности. Пользуешься ли ты React Query? Или у тебя другой фаворит — SWR, TanStack Query, Apollo? Давай обсудим 👇 ✍️ @React_lib

React
2 732
🔥9 полезных функций и хуков, которые пригодятся продвинутому React-разработчику для управления состоянием, оптимизацией и архитектурой компонентов 1. useDebounce Позволяет "отложить" значение — полезно для ввода/поиска.

import { useEffect, useState } from 'react';

export function useDebounce<T>(value: T, delay = 300): T {
  const [debounced, setDebounced] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebounced(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debounced;
}
2. usePrevious Возвращает предыдущее значение пропа или стейта.

import { useRef, useEffect } from 'react';

export function usePrevious<T>(value: T): T | undefined {
  const ref = useRef<T>();
  useEffect(() => {
    ref.current = value;
  }, [value]);
  return ref.current;
}
3. useOnClickOutside Закрытие модалок, дропдаунов при клике вне.

import { useEffect } from 'react';

export function useOnClickOutside(ref: React.RefObject<HTMLElement>, handler: () => void) {
  useEffect(() => {
    const listener = (e: MouseEvent) => {
      if (!ref.current || ref.current.contains(e.target as Node)) return;
      handler();
    };
    document.addEventListener('mousedown', listener);
    return () => document.removeEventListener('mousedown', listener);
  }, [ref, handler]);
}
4. useIsMounted Помогает избежать обновления состояния после размонтирования.

import { useEffect, useRef } from 'react';

export function useIsMounted() {
  const ref = useRef(false);
  useEffect(() => {
    ref.current = true;
    return () => { ref.current = false; };
  }, []);
  return ref;
}
5. useEventCallback Запоминает последнюю версию колбэка без повторного рендера.

import { useRef, useCallback } from 'react';

export function useEventCallback<T extends (...args: any[]) => any>(fn: T): T {
  const ref = useRef(fn);
  ref.current = fn;
  return useCallback((...args: any[]) => ref.current(...args), []) as T;
}
6. useAsync Асинхронный вызов с контролем загрузки, ошибок и результата.

import { useState, useCallback } from 'react';

export function useAsync<T>(asyncFn: () => Promise<T>) {
  const [loading, setLoading] = useState(false);
  const [data, setData] = useState<T | null>(null);
  const [error, setError] = useState<unknown>(null);

  const run = useCallback(async () => {
    setLoading(true);
    setError(null);
    try {
      const result = await asyncFn();
      setData(result);
    } catch (e) {
      setError(e);
    } finally {
      setLoading(false);
    }
  }, [asyncFn]);

  return { loading, data, error, run };
}
7. useLocalStorage Простой хук для хранения данных в localStorage.

import { useState, useEffect } from 'react';

export function useLocalStorage<T>(key: string, initial: T) {
  const [value, setValue] = useState<T>(() => {
    const json = localStorage.getItem(key);
    return json ? JSON.parse(json) : initial;
  });

  useEffect(() => {
    localStorage.setItem(key, JSON.stringify(value));
  }, [key, value]);

  return [value, setValue] as const;
}
8. useMediaQuery Работа с медиа-запросами в React без CSS.

import { useEffect, useState } from 'react';

export function useMediaQuery(query: string): boolean {
  const [matches, setMatches] = useState(() => window.matchMedia(query).matches);

  useEffect(() => {
    const media = window.matchMedia(query);
    const listener = () => setMatches(media.matches);
    media.addEventListener('change', listener);
    return () => media.removeEventListener('change', listener);
  }, [query]);

  return matches;
}
9. useToggle Бинарный переключатель состояния (on/off).

import { useCallback, useState } from 'react';

export function useToggle(initial = false) {
  const [state, setState] = useState(initial);
  const toggle = useCallback(() => setState(prev => !prev), []);
  return [state, toggle] as const;
}
✍️ @React_lib

React
2 732
🚀 Как ускорить загрузку React-приложения? 5 реальных советов Сегодня покажу, как я оптимизирую загрузку фронтенда в продакше
🚀 Как ускорить загрузку React-приложения? 5 реальных советов Сегодня покажу, как я оптимизирую загрузку фронтенда в продакшене. Это помогает не только SEO, но и удерживает пользователя, который мог бы уйти, не дождавшись загрузки. Вот 5 проверенных приёмов: 1. Code Splitting (разделение кода) Используйте React.lazy и Suspense, чтобы грузить компоненты только при необходимости. Особенно полезно для роутинга. 2. Tree shaking Убедитесь, что сборщик (Webpack, Vite) удаляет неиспользуемый код. Проверь, чтобы библиотеки импортировались модульно (import { Button } from 'lib', а не всё подряд). 3. Оптимизация картинок Используйте современные форматы (WebP, AVIF) и lazy загрузку изображений, чтобы не тянуть весь хлам сразу. 4. Минификация и сжатие Включите GZIP или Brotli на сервере. Также обязательно минифицируйте JS/CSS. 5. Critical CSS и SSR/SSG Подумайте об использовании Next.js или аналогов. Они помогают загрузить только нужный CSS и HTML прямо на старте, особенно полезно для первых 3 секунд. ❓А какие техники используете вы, чтобы ускорить загрузку? ✍️ @React_lib