True Frontender
1.02K subscribers
143 photos
7 videos
89 links
Сборная солянка про фронтенд.

JavaScript, React, TypeScript, HTML, CSS — здесь обсуждаем всё, что связано с веб-разработкой!

Связь: @pmowq
Download Telegram
Как работает React.memo и когда его следует использовать? В этой статье мы рассмотрим основы мемоизации компонентов в React.

-> Читать статью

#react
👍51🔥1👀1
Разница между useEffect и useLayoutEffect в React

Хуки useEffect и useLayoutEffect в React часто вызывают путаницу из-за их схожести. Оба хука предназначены для выполнения побочных эффектов в функциональных компонентах, но они имеют ключевые различия в тайминге их выполнения.

useEffect
useEffect используется для выполнения побочных эффектов в компоненте, таких как запросы данных, подписки или ручные изменения в DOM, которые не требуют немедленного выполнения и не блокируют визуальные обновления.

Особенности:
-
Выполняется после отрисовки и коммита компонента в DOM.
- Не блокирует визуальные обновления, что делает его идеальным для большинства побочных эффектов.
- Используется для взаимодействий с внешними API и выполнения асинхронных операций.

useLayoutEffect
useLayoutEffect работает аналогично useEffect, но вызывается синхронно после всех изменений DOM, но перед перерисовкой на экране. Это значит, что все изменения, выполненные в useLayoutEffect, будут отражены на экране сразу после его выполнения.

Особенности:
- Выполняется синхронно после всех изменений DOM, но до перерисовки.
- Используется для чтения или изменения DOM до того, как пользователь увидит обновления.
- Может вызывать блокировку визуальных обновлений, если содержит тяжелые вычисления.

Ключевые различия:
- useEffect выполняется после отрисовки компонента, позволяя выполнять побочные эффекты без блокировки визуальных обновлений, в то время как useLayoutEffect выполняется непосредственно после изменений в DOM и перед перерисовкой, что идеально подходит для задач, требующих немедленного чтения или изменения DOM.
- Использование useLayoutEffect может привести к заметным задержкам в визуальных обновлениях, особенно если в нем содержатся тяжелые вычисления, тогда как useEffect не оказывает такого влияния на процесс рендеринга.
- В большинстве случаев предпочтительнее использовать useEffect для обработки побочных эффектов, а useLayoutEffect следует использовать только тогда, когда необходимо синхронно взаимодействовать с DOM, например для измерения размеров элемента перед его отображением.

Заключение
Выбор между useEffect и useLayoutEffect зависит от требований к побочным эффектам в вашем компоненте. Хотя useEffect является наиболее часто используемым хуком для побочных эффектов из-за его не блокирующего поведения, useLayoutEffect предоставляет необходимую синхронность для определенных сценариев работы с DOM. Важно правильно выбирать между ними, чтобы обеспечить эффективную работу приложения и хороший пользовательский опыт.

#react
👍11🔥41
useImperativeHandle в React: хук, о котором Вы, возможно, не знали

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

Как работает useImperativeHandle
useImperativeHandle обычно используется в сочетании с forwardRef и позволяет родительскому компоненту вызывать специфические функции дочернего компонента. Это может быть полезно для управления фокусом, триггеринга анимаций или других действий, которые должны быть инициированы родительским компонентом, но выполнены дочерним.

Пример использования
Давайте рассмотрим пример, где у нас есть TextInput, и мы хотим, чтобы родительский компонент мог вызывать его метод focus.

import React, { useRef, useImperativeHandle } from 'react';

const TextInput = React.forwardRef((props, ref) => {
const inputRef = useRef();

useImperativeHandle(ref, () => ({
focus: () => {
inputRef.current.focus();
}
}));

return <input ref={inputRef} type="text" />;
});

function ParentComponent() {
const textInputRef = useRef();

const focusTextInput = () => {
textInputRef.current.focus();
};

return (
<>
<TextInput ref={textInputRef} />
<button onClick={focusTextInput}>Focus on Input</button>
</>
);
}


В этом примере useImperativeHandle используется для предоставления родительскому компоненту метода focus, позволяя управлять фокусом текстового поля.

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

#react
👍9🔥3👨‍💻21
Всем привет! Как проходят ваши выходные? 🏖
Сегодня поговорим о важной, но иногда недооцененной особенности в React - ключах. Это тема, которая может показаться незначительной на первый взгляд, но на самом деле играет важную роль в поведении наших React-приложений.

Что такое ключи и зачем они нужны?
Ключи в React - это специальные атрибуты строкового типа, которые мы присваиваем элементам при их рендеринге. Они помогают React определять, какие элементы были изменены, добавлены или удалены.

Пример
const todoList = todos.map((todo) =>
<li key={todo.id}>{todo.text}</li>
);


Почему ключи важны?
- Ключи помогают React оптимизировать процесс обновления DOM. Когда ключи отсутствуют или неправильно назначены, React может тратить больше ресурсов на ненужные операции, например, на перерисовку всего списка вместо обновления одного элемента.
- Неправильное использование ключей может привести к странным багам, например, некорректному сохранению состояния компонентов.

Как работают ключи под капотом
Когда React рендерит список, он использует ключи для сопоставления элементов с их предыдущими состояниями. Это позволяет React выполнять только необходимые обновления в DOM, что значительно повышает производительность.

Идеальный ключ должен быть:
- Уникальным для каждого элемента в списке.
- Постоянным и не меняться при повторных рендерингах.

Лучшие практики:
- Используйте уникальные идентификаторы из ваших данных, например, ID из базы данных.
- Если уникальный ID отсутствует, подумайте над логически уникальным способом генерации ключей.

Заключение
Ключи - это не просто дополнительные атрибуты, а мощный инструмент, который обеспечивает эффективную и правильную работу наших приложений. Правильное использование ключей помогает избежать множества проблем, связанных с производительностью и поведением компонентов.

#react
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🆒31🤔1👾1
Привет! Сегодня наша тема – хук useReducer в React. Все знакомы с useState, но useReducer зачастую уходит в тень, хотя предлагает великолепные возможности для управления состоянием.

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

Как работает useReducer?
useReducer принимает три аргумента:
1. Функция, которая определяет, как состояние должно изменяться в ответ на определённые действия. Эта функция принимает текущее состояние и действие в качестве аргументов и возвращает новое состояние.
function reducer(state, action) {
switch (action.type) {
// логика обработки действий
}
}


2. Начальное состояние, которое будет использоваться в первый момент, когда компонент рендерится.
const initialState = { count: 0 };


3. Необязательная функция для расчета начального состояния. Она принимает начальное состояние в качестве аргумента и возвращает фактическое начальное состояние.
function init(initialState) {
// Сложная логика для определения начального состояния
return initialState;
}


После инициализации useReducer, вы получите доступ к двум элементам: текущему состоянию и функции dispatch. Функция dispatch используется для отправки действий в ваш reducer.

Пример использования
Давайте рассмотрим классический пример - счётчик. С useState вы бы сделали это так:
const [count, setCount] = useState(0);

const increment = () => setCount(prevCount => prevCount + 1);
const decrement = () => setCount(prevCount => prevCount - 1);


Теперь давайте реализуем тот же счётчик, но уже с useReducer:
const initialState = { count: 0 };

function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'decrement':
return { ...state, count: state.count - 1 };
default:
return state
}
}

const [state, dispatch] = useReducer(reducer, initialState);

// Использование:
dispatch({ type: 'increment' });
dispatch({ type: 'decrement' });


Видите разницу? Вместо прямой модификации состояния, мы отправляем "действие" (action), которое описывает, что именно нужно сделать. Это упрощает отслеживание изменений состояния и делает код более предсказуемым.

Заключение
useReducer - позволяет сделать код более структурированным и упрощает управление сложными состояниями. Использование useReducer не всегда необходимо, но в сложных сценариях он становится настоящим спасением.

#react
👍10🔥53👾3
Привет! Сегодня мы разберем классическую джуновскую задачу с собеседований. Мы узнаем, как определить количество повторений каждого элемента в массиве.

Задача
У нас есть массив, который может содержать как уникальные, так и повторяющиеся элементы. Наша цель - выяснить, сколько раз каждый элемент встречается в этом массиве.

Пример
Возьмем массив хештегов: ["#javascript", "#react", "#patterns", "#css", "#interview", "#javascript", "#css"]. Нам нужно определить, сколько постов приходится на каждый хештег.

Алгоритм решения:
1. Начинаем с пустого объекта, который будет хранить элементы массива как ключи и их количество как значение.
2. Используем метод reduce для перебора каждого элемента в массиве.
3. Проверяем, существует ли уже такой ключ в аккумуляторе. Если да, увеличиваем его значение на 1. Если нет - создаем ключ с начальным значением 1.
4. После обработки всех элементов возвращаем аккумулятор как результат функции.

Решение
function countElements(arr) {
return arr.reduce((acc, element) => {
acc[element] = (acc[element] || 0) + 1;
return acc;
}, {});
}

// Пример использования
const tags = ["#javascript", "#react", "#patterns", "#css", "#interview", "#javascript", "#css"]
console.log(countElements(tags));


А вы встречали подобные задачи? Делитесь своими мыслями о других способах решения этой задачи или предлагайте свои задачи на будущие разборы.

#interview #javascript
👍19🔥54👾2
Давно не было постов про React. Пора это исправлять) Сегодня про встроенную поддержку метаданных в 19 версии реакта. Теперь можно легко задавать <title>, <meta> и <link> прямо внутри компонентов, без сторонних библиотек.

Что это за фича?
Раньше для изменения метаданных страницы нужно было использовать такие библиотеки, как react-helmet. Но теперь всё стало намного проще, так как React позволяет добавлять метаданные прямо в код компонента, а обновление тегов выполняется автоматически.

Как это работает?
Метаданные можно описывать прямо в JSX, и React автоматически добавит их в <head> страницы.

Пример:

const Post = ({ post }) => {
return (
<article>
<h1>{post.title}</h1>
<title>{post.title}</title>
<meta name="description" content={post.description} />
<meta name="keywords" content={post.keywords.join(', ')} />
<link rel="canonical" href={post.url} />
<p>{post.content}</p>
</article>
);
}


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

Почему это удобно?
Теперь метаданные задаются прямо в коде React-компонента.
Всё обновляется автоматически при изменении компонента.
Никаких дополнительных зависимостей или сложных настроек.

Кто-нибудь уже успел попробовать или еще сидите на 18 версии?

#react #BestPractices
🔥13👍5👀22
Сегодня о концепции, которая уже сейчас вызывает много обсуждений – signals. Что это такое, почему это может изменить ваш подход к управлению состоянием.

Что такое Signals?
Signals – это реактивные примитивы, позволяющие:
1. Декларативно хранить состояние. Вместо традиционных хуков, таких как useState или useEffect, вы работаете с сигналами, которые автоматически отслеживают изменения.

2. Минимизировать лишние перерисовки. Обновляются только те компоненты, которые непосредственно зависят от изменившегося значения.

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

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

Как использовать Signals в реакте?
1. Установите пакет @preact/signals-react.
2. Настройте вашу сборку или используйте хук useSignals
3. Импортируйте функцию signal из пакета и создайте реактивное значение:

import React from 'react';
import { signal } from '@preact/signals-react';

const count = signal(0);

function Counter() {
return (
<div>
<h3>Счетчик: {count.value}</h3>
<button onClick={() => count.value++}>Увеличить</button>
</div>
);
}

export default Counter;


В этом примере:
1. Функция signal(0) создаёт реактивное значение count с начальным значением 0.
2. Компонент перерисовывается автоматически при изменении count.value, избавляя вас от необходимости использовать setState или другие хуки для управления обновлением UI.

Итог
Пакет @preact/signals-react предлагает новый способ управления состоянием, позволяя создавать более декларативный и эффективный код за счёт автоматического и точечного обновления компонентов.

Документация по установке тут https://github.com/preactjs/signals/tree/main/packages/react

#react #Perfomance #JavaScript
👍10🔥3
Привет! Давно не было реакта. Давайте начнем эту неделю с него)

В React часто нужно привязывать id к элементам, например, для <label> и <input>. Хардкодить id или генерировать их вручную неудобно. В таких случаях поможет хук useId.

Как работает useId?
useId — это хук, который генерирует уникальный идентификатор, оставаясь предсказуемым при ререндере.

import { useId } from "react";

export function Form() {
const id = useId();

return (
<div>
<label htmlFor={id}>Имя:</label>
<input id={id} type="text" />
</div>
);
}



Теперь id для <input> будет уникальным для каждого инстанса компонента, но при этом не будет меняться при ререндере, что важно для правильной работы формы.

Какие проблемы решает useId?
1. Предотвращает дублирование id, создавая уникальные идентификаторы для каждого экземпляра компонента.
2. Ререндеринг не меняет значение id.
3. Избавляет от необходимости хардкодить id, упрощая поддержку кода и предотвращая ошибки при масштабировании компонентов.

Когда использовать useId?
— Для <label> и <input>, чтобы корректно связать их
— Для ARIA-атрибутов (aria-labelledby, aria-describedby)
— Для генерации id в списках без конфликтов

Когда useId не подойдёт?
- Для глобальных id, которые должны быть одинаковыми в разных компонентах

Вывод
useId полезен в формах, сложных UI-компонентах, списках и ARIA-атрибутах. Он избавляет от необходимости хардкодить id и снижает вероятность дублирования.

#react #BestPractices
🔥11👍5
Сегодня у нас кастомный хук — useLatest. Он помогает избежать проблем с устаревшими данными в замыкании.

В чём проблема?
Когда передаём состояние в асинхронную функцию, оно остаётся таким, каким было на момент создания функции. В результате в setTimeout, setInterval или обработчиках событий получаем устаревшие значения.


const [count, setCount] = useState(0);

useEffect(() => {
const interval = setInterval(() => {
console.log(count); // Всегда 0
}, 1000);

return () => clearInterval(interval);
}, []);


Решение через кастомный хук useLatest
1. Создадим кастомный хук:

function useLatest(value) {
const ref = useRef(value);

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

return ref;
}


2. Теперь будем получать актуальное значение внутри useEffect:

const [count, setCount] = useState(0);
const countRef = useLatest(count);

useEffect(() => {
const interval = setInterval(() => {
console.log(countRef.current); // Всегда актуальное значение count
}, 1000);

return () => clearInterval(interval);
}, []);



Почему не просто useRef?
useLatest инкапсулирует всю логику в одном месте, что делает код чище и надёжнее.

#react #BestPractices
👍9🔥4
Привет! Давайте начнем эту неделю с необычной для понедельника темы — поговорим о валидации форм в React.

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

Пример

import { z } from "zod";

const userSchema = z.object({
name: z.string(),
age: z.number().min(18),
});

const result = userSchema.safeParse({ name: "Антон", age: 42 });

if (!result.success) {
console.log(result.error.format()); // Ошибка: возраст должен быть 18+
}


Zod + TypeScript

type User = z.infer<typeof userSchema>;


User — это автоматически сгенерированный тип, который всегда соответствует схеме.

Простая валидация формы
Используем Zod вместе с React Hook Form, чтобы валидировать форму без лишнего кода.

import { useForm } from "react-hook-form";
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";

const formSchema = z.object({
email: z.string().email(),
password: z.string().min(6, "Пароль должен содержать минимум 6 символов"),
});

type FormData = z.infer<typeof formSchema>;

export function LoginForm() {
const {
register,
handleSubmit,
formState: { errors },
} = useForm<FormData>({
resolver: zodResolver(formSchema),
});

const onSubmit = (data: FormData) => {
console.log("Успешный ввод:", data);
};

return (
<form onSubmit={handleSubmit(onSubmit)}>
<div>
<label>Email:</label>
<input {...register("email")} />
{errors.email && <p>{errors.email.message}</p>}
</div>

<div>
<label>Пароль:</label>
<input type="password" {...register("password")} />
{errors.password && <p>{errors.password.message}</p>}
</div>

<button type="submit">Войти</button>
</form>
);
}


Почему Zod?
- Чистый синтаксис – описание схем читается легко
- Работает с TypeScript – выводит типы автоматически
- Без внешних зависимостей
- Можно использовать в API, формах, конфигурациях

Итог
Zod — это отличный инструмент, который упрощает валидацию данных. Он избавляет от громоздких проверок вручную, отлично интегрируется с TypeScript и React Hook Form и тд

#react #OpenSource #typescript
👏9👍8🔥6
⚡️React становится платным!⚡️

Meta официально объявила, что с 1 апреля 2025 года React переходит на подписку!
Теперь за использование библиотеки придётся платить $9.99/мес для разработчиков и $199/мес для компаний.

Основные изменения:
1️⃣ Бесплатной останется только React 17, но без обновлений.
2️⃣ В React 18+ появится DRM-защита – проект не соберется без лицензионного ключа.
3️⃣ В консоли будет всплывать огромный красный баннер: ⚠️ "React is unlicensed. Please purchase a subscription."
4️⃣ Удалены оптимизации (useMemo, useCallback, React.memo).

Кряк платной версии
На GitHub слили react18-crack.js, который:
Возвращает вырезанный функционал для оптимизации.
Подставляет лицензионный ключ REACT_ENTERPRISE_EDITION=TRUE
Отключает баннер "React is unlicensed" в консоли.

Что делать без кряка?
1️⃣Платить за подписку.
2️⃣ Пересаживаться на Vue.
3️⃣Переписывать всё на jQuery.

#react
Please open Telegram to view this post
VIEW IN TELEGRAM
😁174🤯2🦄21👀1👾1
Использовали хук useDeferredValue? Это хук, который помогает оптимизировать производительность, откладывая обновление менее важных частей интерфейса.

Что за хук?
useDeferredValue — это хук из React 18, который позволяет "откладывать" обновление части интерфейса. Он принимает значение и возвращает его "отложенную" версию. Это значение обновляется только после того, как React завершит рендеринг более приоритетных задач.

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


import { useState, useDeferredValue } from "react";

function App() {
const [query, setQuery] = useState("");
const deferredQuery = useDeferredValue(query);

return (
<div>
<input
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Введите текст"
/>
<List query={deferredQuery} />
</div>
);
}

function List({ query }) {
const items = Array.from({ length: 1000 }, (_, i) => `Item ${i}`);
const filteredItems = items.filter((item) =>
item.toLowerCase().includes(query.toLowerCase())
);

return (
<ul>
{filteredItems.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}


Как это работает?
1. Пользователь вводит текст в инпут.
2. Состояние query обновляется сразу, но deferredQuery обновляется с задержкой.
3. Компонент List использует deferredQuery, чтобы отфильтровать элементы. Благодаря этому:
— Инпут не зависает.
— Фильтрация списка происходит чуть позже, когда React "освободится".

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

#react #BestPractices
👍6🔥2
Одна из распространённых ошибок при работе с React — вызов хуков внутри условий, циклов или вложенных функций 🖼️

Пример кода с ошибкой:

function Component({ show }) {
if (show) {
useEffect(() => {
console.log("Какой-то эффект");
}, []);
}

return <div>Тут что-то интересное!</div>;
}


Ошибка: Invalid hook call

Исправление ошибки:

function Component({ show }) {
useEffect(() => {
if (show) {
console.log("Какой-то эффект");
}
}, [show]);

return <div>Тут что-то интересное!</div>;
}


Почему так происходит?
React запоминает порядок вызова хуков в компоненте и ожидает, что он всегда будет одинаковым. Если хук пропускается из-за условия, на следующем рендере React начинает привязывать хуки не к тем значениям.

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

#react
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥3
Работа с API, кэширование, обновление данных и обработка ошибок — всё это неизбежно возникает в любом приложении. На выбор у нас есть много подходов и инструментов. Один из таких — React Query.

Что такое React Query?
Это библиотека для управления данными в React-приложениях. Она помогает работать с запросами и решает типичные задачи, связанные с их загрузкой, кэшированием, обновлением и обработкой ошибок.

Какие проблемы решает?
1. Вместо написания шаблонного кода для запросов, состояний и обработки ошибок — можно использовать готовые хуки.
2. Данные автоматически кэшируются, и повторные запросы выполняются только при необходимости.
3. Готовые состояния и возможность легко повторить запрос.
4. Минимизирует количество запросов к API за счет кэширования и умной стратегии обновления.
5. Реализация сложных сценариев становится проще.

Как использовать React Query?
1. Установите библиотеку в проект:

npm install @tanstack/react-query


2.Оберните приложение в QueryClientProvider:

import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();

function App() {
return (
<QueryClientProvider client={queryClient}>
<Component />
</QueryClientProvider>
);
}


3. Используйте хуки:
useQuery для загрузки данных:

const { data, isLoading, error } = useQuery({
queryKey: ['todos'],
queryFn: fetchTodos,
});


useMutation для изменения данных:

const { mutate } = useMutation({
mutationFn: updateTodo,
});

mutate({ id: 1, text: 'Updated Todo' });


Преимущества React Query
- Автоматическое кэширование и минимизация запросов.
- Простая обработка ошибок и состояний.
- Гибкость и удобство настройки под любые задачи.

Когда использовать React Query?
- Если проект работает с API.
- Если нужно кэшировать данные и минимизировать количество запросов.


#react #api
👏7👍3🔥2
Привет! Начнем неделю с задачи которой со мной поделился коллега.

Задача:
Написать порядок вывода в консоль и объяснить.

Решение:
Всего у нас будет 2 рендера, так как в коде есть useEffect, который меняет состояние после первого рендера.

1. App — компонент рендерится, выводится лог.
2. useLayoutEffect — этот эффект срабатывает синхронно после обновления DOM.
3. useEffect — эффект после отрисовки интерфейса.
4. App — повторный рендер компонента из-за обновления состояния.
5. useEffect cleanup — очистка эффекта useEffect с предыдущего рендера.
6. useLayoutEffect cleanup — очистка эффекта useLayoutEffect с предыдущего рендера.
7. useLayoutEffect — повторное выполнение синхронного эффекта с обновлённым состоянием.
8. useEffect — повторное выполнение асинхронного эффекта с обновлённым состоянием.

Такой порядок из-за работы React:
- useLayoutEffect вызывается после обновления DOM, но до того, как браузер нарисует изменения на экране.

- useEffect выполняется после отрисовки.

- Функции очистки вызываются перед повторным выполнением эффекта или при размонтировании компонента.

#react #interview
👏13👍6🔥1
На фронтенде производительность — ключевой фактор для хорошего пользовательского опыта. Чем быстрее загружается и работает приложение, тем лучше.
Одним из инструментов оптимизации является динамический импорт. Он позволяет загружать модули только тогда, когда они действительно нужны.

Как это?
Вместо статического импорта:

import { heavyFunc } from './heavyModule.js';

button.addEventListener('click', () => {
heavyFunc();
});


Используем динамический:

button.addEventListener('click', async () => {
const module = await import('./heavyModule.js');
module.heavyFunc();
});


Здесь модуль heavyModule.js загрузится только после клика по кнопке, а не сразу при загрузке страницы.

Зачем?
- Ускоряет загрузку.
- Уменьшает размер основного бандла.

Импорт в React
В React для динамической загрузки компонентов есть React.lazy.

import React, { Suspense } from 'react';

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

function App() {
return (
<Suspense fallback={<div>Загрузка...</div>}>
<LazyComponent />
</Suspense>
);
}


Здесь MyComponent загрузится только при первом рендере LazyComponent.


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

#BestPractices #react #JavaScript
🔥73👍3
Привет! Сегодня разберём интересный момент в React с вызовом нескольких setState в одном обработчике.


function App() {
const [count, setCount] = useState(0);

useEffect(() => {
console.log("Effect:", count);
}, [count]);

const handleClick = () => {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
};

return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>+3</button>
</div>
);
}


Вопрос
Что выведет консоль, и сколько раз сработает useEffect?

Разбор
1. Все три вызова setCount используют одно и то же значение count, так как React не обновляет состояние мгновенно.
2. React батчит вызовы setState в одном событии. В итоге React применяет только последний вызов, и count становится 1.
3. useEffect срабатывает один раз, так как состояние изменилось только один раз.

Вывод в консоль: Effect: 1


Чтобы каждый вызов setCount учитывал предыдущее состояние, используйте функциональное обновление:

function App() {
const [count, setCount] = useState(0);

useEffect(() => {
console.log("Effect:", count);
}, [count]);

const handleClick = () => {
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1);
};

return (
<div>
<p>Count: {count}</p>
<button onClick={handleClick}>+3</button>
</div>
);
}


Теперь каждый вызов setCount получает актуальное значение prev, и count увеличивается правильно, но useEffect всё равно сработает один раз, так как React батчит изменения.

#react
🔥8👍5
Привет! Сегодня разберём StrictMode для разработки в React 🖼️ Он помогает находить потенциальные ошибки и улучшать качество кода.

Что делает StrictMode?
StrictMode активирует дополнительные проверки в режиме разработки:
- Дважды вызывает функции (например, useEffect, useState, конструкторы классов), чтобы выявить побочные эффекты.
- Подскажет, если вы используете методы, которые скоро удалят.
- Находит потенциальные баги, такие как мутации состояния или неправильная работа с хуками.

Как подключить?
Оберните приложение:

ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
);


Советы
- Двойной рендер может раздражать, но он спасает от багов.
- Убедитесь, что useEffect и другие хуки идемпотентны (не ломаются при повторных вызовах).
- Если добавляете StrictMode в легаси проект, будьте готовы к сюрпризам.
- Не отключайте StrictMode без веской причины.

#react #BestPractices
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍3
Уязвимость в React ⚠️

Команда разработки React сообщила об обнаружении критической уязвимости в серверных компонентах React, позволяющей выполнять удалённое выполнение кода на уязвимых серверах, использующих React Server Components.

Что случилось?
Ошибка в механизме обработки данных в RSC даёт возможность злоумышленнику отправить специально сформированный запрос и выполнить произвольный код на сервере без авторизации.

Уязвимость получила идентификатор CVE-2025-5518 и максимальный рейтинг критичности.

Кто в зоне риска?
Затронуты проекты, использующие пакеты react-server-dom-* версий 19.0-19.2.0, в том числе через такие фреймворки, как Next.js, React Router RSC, Vite RSC плагины и другие решения с поддержкой Server Components.

Что делать? ⚠️
React уже выпустил исправления. Достаточно обновить зависимости до 19.0.1, 19.1.2 или 19.2.1. И убедитесь, что используемые фреймворки тоже подтянули фикс.

#react #security
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3