TGViewer
React JS React JS @react_tg · 16.2K subscribers
Post #297 5.01K
🖥 Проблема устаревших замыканий и способы ее решения в React. Часть 1

Замыкания — пожалуй, одна из самых пугающих концепций JavaScript. Даже всезнающий ChatGPT скажет вам это. Во всяком случае, это одна из самых скрытых особенностей языка.

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

Попробуем проникнуть в очередную тайну JavaScript-кода, чтобы выяснить:

🟢что такое замыкания, как они появляются и зачем нужны;
🟢что такое “устаревшее” замыкание и почему оно возникает.

Предупреждение: если вы никогда не сталкивались с замыканиями в React, эта статья может взорвать ваш мозг. Рекомендую запастись достаточным количеством шоколада, чтобы стимулировать клетки мозга во время чтения.

✏️Задача

Представьте, что вы реализуете форму с несколькими полями ввода. Одно из полей представляет собой очень тяжелый компонент из какой-то внешней библиотеки. У вас нет доступа к его внутренним элементам, поэтому вы не можете устранить проблемы с его производительностью. Но этот компонент очень нужен в форме, поэтому вы решили обернуть его в React.memo, чтобы минимизировать повторные рендеринги при изменении состояния формы. Как-то так:
const HeavyComponentMemo = React.memo(HeavyComponent);

const Form = () => {
const [value, setValue] = useState();

return (
<>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<HeavyComponentMemo />
</>
);
};


Пока все хорошо. Тяжелый компонент принимает только одно строковое свойство, например title, и коллбэк onClick. Это происходит при нажатии кнопки “done” (“готово”) внутри компонента. Отправить данные формы также довольно просто: достаточно передать title и onClick.

const HeavyComponentMemo = React.memo(HeavyComponent);

const Form = () => {
const [value, setValue] = useState();
const onClick = () => {
// сюда передаем данные формы
console.log(value);
};

return (
<>
<input
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
<HeavyComponentMemo
title="Welcome to the form"
onClick={onClick}
/>
</>
);
};


А вот теперь перед вами встает дилемма. Как известно, каждое свойство компонента, обернутое в React.memo, должно быть либо примитивным значением, либо постоянным между повторными рендерами. В противном случае мемоизация не сработает. Поэтому технически нужно обернуть onClick в useCallback:

const onClick = useCallback(() => {
// здесь передаем данные
}, []);


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

const onClick = useCallback(() => {
// сюда подаются данные
console.log(value);

// добавление значения к зависимости
}, [value]);


Дилемма заключается в следующем: даже если onClick мемоизирован, он все равно меняется каждый раз, когда кто-то набирает ввод. Поэтому оптимизация производительности бесполезна.

👆 Далее

👆 Часть 2

@react_js
  • 👍 11
  • 🔥 6
  • ❤ 4
More from @react_tg
  1. Oct 2, 2026🔥 Claude Code теперь можно менять изнутри Anthropic представила Mods: небольшие функции н…
  2. Oct 1, 2026Всплывающие скроллеры изображений с анимацией, управляемой прокруткой CSS 🤙 .pop { view-t…
  3. Oct 1, 2026👨‍💻 Фронтенд с AI: что можно делегировать агентам 5 октября, стартует конференция Podlod…
  4. Oct 1, 2026Совет по JavaScript💡 Легко и правильно отображайте цены.
  5. Sep 29, 2026🌦️ Красивый пример того, как может выглядеть современное приложение на Aspire Команда пок…
  6. Sep 24, 2026Temperature displays Индикаторы - это svg-картинки, параметры которых задаются в JS. https…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →