React
2.73K subscribers
321 photos
131 videos
14 files
382 links
Подборки по React js и все что с ним связано. По всем вопросам @evgenycarter
Download Telegram
🎯 Оптимизация ререндеров в React через мемоизацию функций

Многие знают про React.memo, но часто забывают про useCallback — и получают лишние ререндеры, особенно в списках и сложных компонентах.

📌 Проблема:


const handleClick = () => {
console.log('Clicked');
};

<MyButton onClick={handleClick} />


Такой handleClick создаётся заново при каждом рендере. Если MyButton мемоизирован (React.memo), это сломает оптимизацию — пропсы-то изменились!

Решение:


const handleClick = useCallback(() => {
console.log('Clicked');
}, []);


📈 Профит: Функция сохраняется между рендерами, MyButton не ререндерится без причины.

🧠 Особенно важно для:

* Компонентов в списках (map)
* Контейнеров с большим числом коллбеков
* Производительных UI (таблицы, дашборды, графики)

💡 Используйте eslint-плагин react-hooks/exhaustive-deps — он не даст забыть зависимости.

✍️ @React_lib
👍52
🔥 Антипаттерн в React: избыточные зависимости useEffect

Встречали такое?


useEffect(() => {
fetchData(id);
}, [id, fetchData]);


❗️Проблема: fetchData — это функция, которая переопределяется при каждом рендере. В итоге эффект срабатывает чаще, чем должен, даже если id не менялся.

👎 Это вызывает лишние запросы, лаги и баги в логике.

💡 Решения:

1. Обёрнуть в useCallback:


const fetchData = useCallback((id: string) => {
// ...
}, []);


2. Вынести вне компонента (если она не зависит от состояния):


const fetchData = (id: string) => {
// ...
};


3. Игнорировать в зависимостях (как временный хак, но осторожно!):


// eslint-disable-next-line react-hooks/exhaustive-deps


Правильное управление зависимостями в useEffect — ключ к стабильному и предсказуемому поведению компонентов.

✍️ @React_lib
👍7
Сегодня поговорим о Zustand — суперлёгкой и мощной библиотеке для управления состоянием в React-приложениях.


🧵 Минимализм состояния с Zustand

Создание стора занимает меньше минуты:


import { create } from 'zustand';

const useStore = create((set) => ({
count: 0,
increase: () => set((state) => ({ count: state.count + 1 })),
}));


🎯 Как использовать в компоненте:


const Counter = () => {
const { count, increase } = useStore();

return (
<button onClick={increase}>
Count: {count}
</button>
);
};



🧠 Чем хорош Zustand:

* Нет провайдеров.
* Нет бойлерплейта.
* Поддержка middlewares, persist, subscriptions.
* Работает в Next.js, React Native, даже вне React.

Zustand идеально подходит для маленьких и средних приложений. Простой API — максимум гибкости.

✍️ @React_lib
👍7
🚧 TanStack DB — это TypeScript-first библиотека для управления данными и кэшированием, вдохновлённая такими инструментами, как tRPC, TanStack Query, Drizzle, Kysely, RxJS, MobX, Signal, SWR, Zustand и другими.


Что такое TanStack DB?

TanStack DB — это реактивная, абстрактная система управления данными с поддержкой провайдеров и кэшированием, ориентированная на работу с "запросами", "данными" и "реактивностью".

Ты описываешь структуру данных (схему), подключаешь источник данных (провайдер), и всё остальное — магия :

* TanStack DB умеет работать с асинхронными источниками данных
* Обновления реактивны: изменения автоматически отражаются во всех связанных компонентах
* Поддерживаются "live queries" — данные автоматически обновляются при изменении источника
* Под капотом используются сигналы и абстракции, напоминающие RxJS, но с более простым API

https://github.com/TanStack/db

✍️ @React_lib
👍1
Как создать свой кастомный хук usePrevious для хранения предыдущего значения пропсов или стейта в компонентах React.

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


import { useRef, useEffect } from 'react';

/**
* Хук usePrevious сохраняет предыдущее значение value.
* @param {T} value — текущее значение (пропс или стейт)
* @returns {T | undefined} — предыдущий value (или undefined при первом рендере)
*/
function usePrevious(value) {
const ref = useRef();

useEffect(() => {
ref.current = value;
}, [value]);

return ref.current;
}

// Пример использования:
import React, { useState } from 'react';

export default function PriceTracker() {
const [price, setPrice] = useState(100);
const prevPrice = usePrevious(price);

const getTrend = () => {
if (prevPrice === undefined) return '—';
return price > prevPrice ? '📈' : price < prevPrice ? '📉' : '';
};

return (
<div>
<h2>Цена: {price} {getTrend()}</h2>
<button onClick={() => setPrice(p => p + 5)}>↑ Увеличить</button>
<button onClick={() => setPrice(p => p - 5)}>↓ Уменьшить</button>
</div>
);
}


Почему это круто:

* Логика хранения предыдущих значений вынесена в один хук — нет дублирования кода.
* usePrevious работает и для пропсов, и для стейта.
* Помогает сравнивать и реагировать на изменения (анимации, уведомления, условные запросы).

Попробуйте интегрировать usePrevious в свои компоненты, где нужно отслеживать изменение данных во времени. Поделитесь в комментариях, в каких кейсах вы уже использовали или планируете применить такой хук!

✍️ @React_lib
👍7
🔥 Сегодня расскажу о том, как грамотно управлять состоянием форм в React

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

1️⃣ React Hook Form — сейчас это самый популярный способ работы с формами. Отличная производительность, минимальное количество ререндеров и простая интеграция с валидацией.

2️⃣ Formik — проверенная годами библиотека, немного проигрывает в скорости, но выигрывает по удобству работы с комплексными формами и кастомными решениями.

Мой личный совет: используйте React Hook Form для небольших и средних проектов. Если же требуется высокая кастомизация и много логики, Formik остаётся отличным вариантом.

А вы какой способ используете чаще всего? Пишите в комментарии 👇

✍️ @React_lib
👍4😁2
Сегодня хочу поделиться с вами простым, но часто необходимым при работе приёмом: созданием и использованием кастомного хука useFetch для загрузки данных. Часто в React-компонентах мы дублируем один и тот же код: ставим загрузку, устанавливаем состояние для data, error и loading, пишем useEffect, чтобы делать вызов API, очищаем эффекты… Всё это можно обобщить в одном месте и переиспользовать во множестве компонент.

Вот базовая реализация хука useFetch:


import { useState, useEffect, useRef } from 'react';

function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

// Чтобы избежать обновления стейта после размонтирования компонента
const isMounted = useRef(true);

useEffect(() => {
// При монтировании флага меняются
isMounted.current = true;

// Начинаем загрузку
fetch(url)
.then(response => {
if (!response.ok) {
throw new Error(`Ошибка ${response.status}`);
}
return response.json();
})
.then(json => {
if (isMounted.current) {
setData(json);
setLoading(false);
}
})
.catch(err => {
if (isMounted.current) {
setError(err.message);
setLoading(false);
}
});

// Очистка: помечаем, что компонент размонтирован
return () => {
isMounted.current = false;
};
}, [url]);

return { data, loading, error };
}


Разбор ключевых моментов:
1️⃣ useRef для флага isMounted
Если компонент размонтируется до того, как придёт ответ от сервера, вызов setState внутри промиса может вызвать утечку памяти и предупреждение React. Флаг isMounted.current помогает проверить, что компонент ещё жив.

2️⃣ Состояния data, loading, error
Вынесли все три состояния в хук — теперь в компоненте не нужно повторять одно и то же. Достаточно будет написать:


const { data, loading, error } = useFetch('https://api.example.com/posts');


3️⃣ Параметр url в массиве зависимостей
Если url меняется, хук автоматически запустит новую загрузку.

4️⃣ Обработка ошибок
Мы сразу проверяем response.ok, иначе бросаем исключение, и в .catch устанавливаем error.

Теперь пример использования хука в компоненте:


import React from 'react';
import useFetch from './hooks/useFetch';

function PostsList() {
const { data: posts, loading, error } = useFetch('https://jsonplaceholder.typicode.com/posts');

if (loading) {
return <div>Загрузка...</div>;
}

if (error) {
return <div>Ошибка: {error}</div>;
}

return (
<div>
<h2>Список постов</h2>
<ul>
{posts.map(post => (
<li key={post.id}>
<strong>{post.title}</strong>
<p>{post.body}</p>
</li>
))}
</ul>
</div>
);
}

export default PostsList;


Плюсы такого подхода:

* Меньше дублирования кода. Вместо того чтобы копипастить один и тот же useEffect в десятке компонентов, просто импортируем useFetch.
* Централизованная логика. Если понадобится добавить, скажем, кеширование или отмену запроса через AbortController, меняем только внутри useFetch.
* Чистый код в компонентах. Компонент сосредоточен на отображении, а все детали работы с сетью спрятаны в хук.

Советы по улучшению:

* Можно расширить хук, чтобы принимать не только url, но и опции fetch (метод, заголовки и т.п.).
* Добавить параметр deps (зависимости), чтобы перезапускать запрос не только при изменении URL, а при любой другой переменной.
* Использовать AbortController, чтобы отменять запросы при новых вызовах или при размонтировании:
👍5
useEffect(() => {
const controller = new AbortController();
fetch(url, { signal: controller.signal })
.then(/* ... */)
.catch(err => {
if (err.name === 'AbortError') return;
// обработка других ошибок
});
return () => controller.abort();
}, [url]);

* Можно внедрить кеширование: сохранять результаты предыдущих запросов в объекте и отдавать сразу, если URL повторяется.

В итоге кастомный хук useFetch — это простой и мощный инструмент, который сделает ваш код чище и убережёт от типичных ошибок при работе с асинхронными запросами.

✍️ @React_lib
👍7
Понимание React Fiber: как он улучшает производительность рендеринга

React Fiber — это основное обновление, представленное в React 16, которое кардинально изменило способ работы с обновлениями UI, заметно повысив скорость и отзывчивость приложений. Ранее React выполнял все обновления синхронно, из-за чего при крупных изменениях интерфейс мог «подвисать». Fiber решает эту проблему, разбивая рендеринг на мелкие фрагменты, эффективно планируя их выполнение и позволяя браузеру оставаться отзывчивым.

🔑 Главные выводы:
• Инкрементный, асинхронный рендеринг вместо монолитных обновлений
• Приоритезация задач: важные обновления обрабатываются в первую очередь
• Поддержка Concurrent Mode и Suspense
• Преимущества работают «из коробки» на React 16+


Что такое React Fiber?

Это новый reconciler в React, заменивший старый «стековый» алгоритм.
Старый reconciler: синхронный, блокирует UI при большом числе изменений.
Fiber-reconciler: разбивает работу на мелкие, прерываемые задачи — UI остаётся плавным.


Как Fiber улучшает производительность

Time Slicing (инкрементный рендеринг)
Fiber делит рендеринг на крошечные задачи, выполняемые между фреймами анимации, чтобы не блокировать основной поток.

Приоритезация обновлений
Сначала обрабатываются срочные задачи (например, ввод пользователя), менее важные откладываются до «паузы» браузера.

🤝 Concurrent Mode
Позволяет приостанавливать, возобновлять и отменять нерелевантные задачи, сохраняя интерфейс отзывчивым.


Ключевые фичи Fiber

* Улучшенный reconciler: минимизирует количество операций с DOM
* Планирование задач: плавный UX при множестве одновременных обновлений
* Concurrent Mode и Suspense: асинхронная загрузка без «заморозок» UI


Пример на React 18: useTransition


import { useTransition } from 'react';

function FilterList({ items }) {
const [filtered, setFiltered] = useState(items);
const [isPending, startTransition] = useTransition();

const handleChange = e => {
const q = e.target.value;
startTransition(() => {
setFiltered(items.filter(item => item.includes(q)));
});
};

return <input onChange={handleChange} placeholder="Фильтр…" />;
}



Советы по оптимизации

• Используйте React.memo и useMemo для предотвращения лишних перерисовок
• Lazy-загрузка и code-splitting с React.lazy и Suspense
• Windowing для длинных списков (библиотеки `react-window`)
• React Profiler для поиска узких мест


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

https://blog.openreplay.com/understanding-react-fiber-improves-rendering-performance/

✍️ @React_lib
👍21
Как анимировать появление компонентов в React с помощью Framer Motion. Это один из тех инструментов, который делает твой интерфейс живым, без особых усилий.

🎬 Пример анимации при маунте:


import { motion } from 'framer-motion'

const FadeIn = ({ children }: { children: React.ReactNode }) => (
<motion.div
initial={{ opacity: 0, y: 10 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.3 }}
>
{children}
</motion.div>
)


Используй его просто как обёртку:


<FadeIn>
<Card>Контент</Card>
</FadeIn>


Где использовать?

🔘Модалки
🔘Всплывающие подсказки
🔘Новые элементы списка
🔘Контент, который появляется после загрузки

Такая анимация делает взаимодействие с интерфейсом приятнее, особенно если тебе важна микроанимация и внимание к деталям. Framer Motion — мощный, но можно начать с малого.

✍️ @React_lib
👍2
🔧 Шпаргалка по базовым компонентам React



// Импорт React и роутера
import React, { useState, useEffect, createContext, useContext } from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';

// 1. Создание контекста
const MyContext = createContext();

// 2. Компонент с Context и useEffect
function Welcome() {
const contextValue = useContext(MyContext);

useEffect(() => {
console.log("Welcome component mounted or updated");
return () => console.log("Welcome component unmounted");
}, []);

return <h1>{contextValue}</h1>;
}

// 3. Управляемая форма
function FormComponent() {
const [inputValue, setInputValue] = useState('');
const handleChange = (e) => setInputValue(e.target.value);

return (
<div>
<h2>Controlled Form</h2>
<input type="text" value={inputValue} onChange={handleChange} />
<p>Input Value: {inputValue}</p>
</div>
);
}

// 4. Счётчик с состоянием и обработчиком
function Counter() {
const [count, setCount] = useState(0);

return (
<div>
<h2>Counter</h2>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

// 5. Рендер списка
function FruitList() {
const fruits = ['Apple', 'Banana', 'Orange'];
return (
<div>
<h2>Fruit List</h2>
<ul>
{fruits.map((fruit, index) => (
<li key={index}>{fruit}</li>
))}
</ul>
</div>
);
}

// 6. Условный рендеринг
function ConditionalRender({ isLoggedIn }) {
return (
<div>
<h2>Conditional Rendering</h2>
{isLoggedIn ? <p>Welcome back!</p> : <p>Please log in.</p>}
</div>
);
}

// 7. Навигация
function Navigation() {
return (
<nav>
<Link to="/">Home</Link> | <Link to="/form">Form</Link> | <Link to="/counter">Counter</Link> | <Link to="/fruits">Fruits</Link>
</nav>
);
}

// 8. Основной App с Router и Context
function App() {
return (
<MyContext.Provider value="Hello, Context!">
<Router>
<div style={{ padding: '20px', fontFamily: 'Arial' }}>
<Navigation />
<Switch>
<Route path="/" exact>
<Welcome />
<ConditionalRender isLoggedIn={true} />
</Route>
<Route path="/form" component={FormComponent} />
<Route path="/counter" component={Counter} />
<Route path="/fruits" component={FruitList} />
</Switch>
</div>
</Router>
</MyContext.Provider>
);
}

export default App;


✍️ @React_lib
👍6
🚀 Как ускорить загрузку 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
👍7
🔥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
👍112
🧠 Зачем нужен 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
👍123💩1
This media is not supported in your browser
VIEW IN TELEGRAM
Правило ESLint для обнаружения избыточного состояния в React

✍️ @React_lib
👍5
Media is too big
VIEW IN TELEGRAM
Секреты 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
🔥31
⚛️ Как я ускоряю загрузку 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
👍4
📊 Tremor — готовые React-компоненты для дашбордов.

Tremor предлагает более 35 настраиваемых и доступных компонентов React для создания информационных панелей и современных веб-приложений. Создан на основе Tailwind CSS и Radix UI.

https://github.com/tremorlabs/tremor

✍️ @React_lib
👍3
This media is not supported in your browser
VIEW IN TELEGRAM
Возможно, вам не нужен useEffect (версия с ref‑колбэками)

В React хук useEffect часто используют для выполнения кода после монтирования компонента: подписки, измерения DOM-элементов, вызовы API и т. д. Но в некоторых случаях — особенно когда нам нужно только получить доступ к DOM-элементуuseEffect оказывается избыточным.

Что предлагают вместо useEffect?

Ref-колбэки.
Вместо того чтобы ждать монтирования и использовать useEffect, можно передать функции-колбэку ссылку (ref). Этот колбэк автоматически вызовется, когда элемент появится или исчезнет в DOM.

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

- Для измерения DOM (размеры, позиция).
- Для инициализации библиотек, которые работают с элементом.
- Для управления фокусом.

Если нужно реагировать на изменения состояния или выполнять сложные сайд-эффекты — тогда useEffect остаётся правильным выбором.

✍️ @React_lib
👍101
Как я ускоряю разработку с помощью React DevTools

Сегодня хочу поделиться инструментом, без которого я уже не представляю работу — React DevTools.
Многие его ставят "для галочки", но реально используют только для просмотра компонентов. А ведь он может сильно ускорить разработку, если выжать из него максимум.

Вот что реально помогает:

1. Профайлер — если у вас страница перерисовывается дольше, чем хотелось бы, откройте вкладку Profiler. Там видно, какие компоненты рендерятся лишний раз и сколько это занимает времени.
2. Поиск по дереву компонентов — если проект большой, можно быстро найти нужный компонент прямо в DevTools (Cmd/Ctrl + F).
3. Редактирование пропсов на лету — в режиме разработчика можно менять пропсы и сразу видеть результат без пересборки проекта.
4. Highlight updates — включает подсветку обновляемых компонентов. Очень удобно, чтобы найти “лишние” рендеры.

Если вы еще не используете хотя бы профайлер и подсветку рендеров — попробуйте. Уже через пару дней вы начнете понимать, где проект "проседает" и что можно оптимизировать.

А вы часто заглядываете в Profiler или больше по старинке — console.log и догадки? 😄

✍️ @React_lib
👍9
Всем доброго вечера! Сегодня я хочу рассказать вам о проблеме, которая встречается почти у каждого React-разработчика - "эффект дрожания" интерфейса при условном рендеринге.

Допустим, у вас есть компонент, который отображает список данных после загрузки. Пока данные подгружаются, вы показываете спиннер, а потом - сам список. Всё вроде нормально… но при переключении состояния верстка “прыгает”, элементы смещаются, и пользователь видит неприятный скачок.

💡 Как решить?
Главная идея — зарезервировать место под контент заранее. Даже если мы показываем скелетон или спиннер, блок должен иметь такую же высоту, как и итоговый контент.
Например:


{isLoading ? (
<div style={{ height: 300 }}>
<Spinner />
</div>
) : (
<List items={data} />
)}


А ещё лучше — использовать скелетон-загрузчик (skeleton loader). Он повторяет форму будущего контента, и благодаря этому переключение происходит плавно и без сдвигов.

📌 Совет: в UI-библиотеках вроде Material UI или Ant Design уже есть готовые скелетоны - просто используйте их вместо "чистого" спиннера. Пользователь не заметит перехода, и приложение будет казаться быстрее.

А у вас бывает, что верстка дергается при смене состояния? Как вы это решаете?

✍️ @React_lib
👍51👎1