📌 Питання:
Чи правильно написаний цей компонент?
function ProductList({ products }) {
const [visibleProducts, setVisibleProducts] = useState([]);
useEffect(() => {
setVisibleProducts(
products.filter(product => product.inStock)
);
}, [products]);
return (
<ul>
{visibleProducts.map(product => (
<li key={product.id}>
{product.name}
</li>
))}
</ul>
);
}
📌 Очікувана відповідь:
У цьому випадку
useEffect не потрібен.visibleProducts — це derived data, яку можна отримати безпосередньо з products під час render:
function ProductList({ products }) {
const visibleProducts = products.filter(
product => product.inStock
);
return (
<ul>
{visibleProducts.map(product => (
<li key={product.id}>
{product.name}
</li>
))}
</ul>
);
}
У першому варіанті ми створюємо зайвий цикл:
render
↓
useEffect↓
setState↓
ще один render
Крім того, ми зберігаємо у
state значення, яке можна просто отримати з уже наявних props.📌 Коли useEffect справді потрібен?
Коли потрібно синхронізувати React із зовнішньою системою: наприклад, subscription, timer, DOM API, WebSocket або сторонньою бібліотекою.
Якщо ж derived calculation справді дорогий, тоді можна розглядати memoization — але це не причина переносити derived data у
state.5. Чому компонент може render’итися, навіть якщо його props не змінилися?
📌 Питання:
Чому
Child може повторно render’итися при кожному натисканні?
function Parent() {
const [count, setCount] = useState(0);
return (
<>
<button onClick={() => setCount(c => c + 1)}>
{count}
</button>
<Child name="John" />
</>
);
}
function Child({ name }) {
console.log('Child render');
return <div>{name}</div>;
}
📌 Очікувана відповідь:
У React без автоматичної memoization, коли
Parent render’иться повторно, React за замовчуванням також виконує його дочірні компоненти.Те, що
props Child не змінилися, саме по собі не означає, що React пропустить його render.Якщо є реальна потреба уникнути такого render, можна використати
React.memo:
const Child = React.memo(function Child({ name }) {
console.log('Child render');
return <div>{name}</div>;
});
Але тут важливо розуміти reference equality.
Наприклад:
<Child options={{ theme: 'dark' }} />
На кожному render
Parent створюється новий object.Тобто навіть якщо його вміст однаковий:
{ theme: 'dark' } !== { theme: 'dark' }
Це різні object references.
Тому така prop може завадити
React.memo пропустити render.📌 А що з React Compiler?
Якщо проєкт використовує
React Compiler, він може автоматично застосовувати memoization і пропускати частину зайвих render’ів без ручного React.memo.Тому
React.memo — не універсальна кнопка «зробити швидше».Спочатку потрібно зрозуміти, чи є повторний render реальною performance-проблемою і чи не виконує потрібну оптимізацію Compiler.
🍀 Що об'єднує ці питання?
На співбесіді важливо не просто знати API React, а розуміти, чому код поводиться саме так.
Тому вчіть не тільки
useEffect, useCallback, useMemo чи React.memo, а й:JavaScript closures, React render model, state, component identity, Effects та memoization.
Вчіть не відповіді. Вчіть логіку. Удачі!
TikTok | Instagram | Telegram