Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Какое сравнение в PureComponent
PureComponent — один из способов оптимизации в React, который автоматически предотвращает ненужные перерисовки. Этот вопрос проверяет глубокое понимание механизма сравнения и шаллоу компаресона.
Что такое PureComponent
import React from 'react';
// Обычный Component
class RegularComponent extends React.Component {
render() {
return <div>{this.props.name}</div>;
}
}
// PureComponent - имеет встроенное неглубокое сравнение
class PureComp extends React.PureComponent {
render() {
return <div>{this.props.name}</div>;
}
}
Shallow Comparison (Неглубокое сравнение)
PureComponent использует shallow equality — поверхностное сравнение.
// Shallow comparison работает так:
function shallowEqual(obj1, obj2) {
// 1. Проверяет типы
if (typeof obj1 !== typeof obj2) return false;
// 2. Проверяет примитивы
if (obj1 === obj2) return true;
// 3. Для объектов - сравнивает только первый уровень
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
// 4. Сравнивает значения поверхностно
for (let key of keys1) {
if (obj1[key] !== obj2[key]) {
return false; // Используется === для каждого свойства
}
}
return true;
}
Как PureComponent сравнивает props и state
PureComponent сравнивает:
- Props — поверхностно (shallow)
- State — поверхностно (shallow)
class UserCard extends React.PureComponent {
render() {
const { user, tags } = this.props;
return (
<div>
<h1>{user.name}</h1>
<p>Tags: {tags.join(", ")}</p>
</div>
);
}
}
// КЕЙС 1: Примитивные значения
const user1 = { name: "Alice" };
const user2 = { name: "Alice" };
user1 === user2; // false - разные объекты
// PureComponent НЕ перерисуется, если получит user1, потом user2?
// НЕТ! Потому что user1 !== user2
// КЕЙС 2: Одинаковые ссылки
const user = { name: "Alice" };
// Переда user дважды
// PureComponent НЕ перерисуется - потому что === совпадает
// КЕЙС 3: Вложенные объекты
const user = { name: "Alice", address: { city: "NYC" } };
const newUser = { name: "Alice", address: { city: "NYC" } };
// Shallow comparison НЕ сравнит address.city!
// PureComponent ПЕРЕРИСУЕТСЯ, хотя address содержит одинаковые данные
Практические примеры
Пример 1: Работает корректно
class UserProfile extends React.PureComponent {
render() {
const { id, name, age } = this.props;
return <div>{name} ({age})</div>;
}
}
// Передаем примитивные значения
<UserProfile id={1} name="Alice" age={25} />
// Если id, name, age не изменились - PureComponent НЕ перерисуется
Пример 2: Проблема с объектами
class UserProfile extends React.PureComponent {
render() {
const { user } = this.props;
return <div>{user.name}</div>;
}
}
function Parent() {
const [count, setCount] = useState(0);
// ПРОБЛЕМА: новый объект создается при каждом рендере
const user = { name: "Alice" }; // новая ссылка каждый раз!
return (
<div>
<UserProfile user={user} />
{/* UserProfile ВСЕГДА перерисуется,
потому что user - новый объект */}
<button onClick={() => setCount(count + 1)}>Update</button>
</div>
);
}
Пример 3: Решение проблемы
function Parent() {
const [count, setCount] = useState(0);
// Используем useMemo для стабильной ссылки
const user = useMemo(() => ({ name: "Alice" }), []);
return (
<div>
<UserProfile user={user} />
{/* UserProfile НЕ перерисуется, потому что ссылка на user стабильна */}
<button onClick={() => setCount(count + 1)}>Update</button>
</div>
);
}
Сравнение !== и ==="
PureComponent использует === для сравнения:
// === сравнивает ссылки для объектов
const obj1 = { a: 1 };
const obj2 = { a: 1 };
obj1 === obj2; // false - разные ссылки
obj1.a === obj2.a; // true - одинаковые значения
// Shallow сравнение проходит ВСЕ уровни второго порядка
const obj1 = { a: 1, b: 2 };
const obj2 = { a: 1, b: 2 };
shallowEqual(obj1, obj2); // true - все свойства === совпадают
// Но вложенные объекты сравниваются по ссылке
const obj1 = { a: 1, nested: { x: 1 } };
const obj2 = { a: 1, nested: { x: 1 } };
shallowEqual(obj1, obj2); // false - nested !== nested
Различие: Component, PureComponent, memo
// 1. Component - всегда перерисовывается
class MyComponent extends React.Component {
render() {
return <div>{this.props.value}</div>;
}
}
// Перерисуется при ЛЮБОМ изменении родителя
// 2. PureComponent - shallow сравнение props/state
class MyPureComponent extends React.PureComponent {
render() {
return <div>{this.props.value}</div>;
}
}
// Перерисуется только если props/state изменились (shallow)
// 3. React.memo - функциональный компонент с shallow сравнением
const MyMemoComponent = React.memo(function MyComponent({ value }) {
return <div>{value}</div>;
});
// Перерисуется только если props изменились (shallow)
// 4. React.memo с custom компаратором
const MyMemoComponent = React.memo(
function MyComponent({ value, nested }) {
return <div>{value}</div>;
},
(prevProps, nextProps) => {
// Возвращает true если пропсы равны (НЕ перерисовывать)
return prevProps.value === nextProps.value;
}
);
Когда PureComponent неэффективен
class DataTable extends React.PureComponent {
render() {
const { data } = this.props;
return (
<div>
{data.map(item => <div key={item.id}>{item.name}</div>)}
</div>
);
}
}
function Parent() {
const [count, setCount] = useState(0);
// ПРОБЛЕМА: массив пересоздается при каждом рендере
const data = [
{ id: 1, name: "Item 1" },
{ id: 2, name: "Item 2" }
];
return (
<div>
<DataTable data={data} />
{/* DataTable ВСЕГДА перерисуется,
потому что data - новый массив */}
<button onClick={() => setCount(count + 1)}>Update</button>
</div>
);
}
Решение: использование useMemo
function Parent() {
const [count, setCount] = useState(0);
// Мемоизируем данные
const data = useMemo(() => [
{ id: 1, name: "Item 1" },
{ id: 2, name: "Item 2" }
], []); // Пустой deps - создается один раз
return (
<div>
<DataTable data={data} />
{/* DataTable НЕ перерисуется */}
<button onClick={() => setCount(count + 1)}>Update</button>
</div>
);
}
Производительность shallow сравнения
const obj1 = { a: 1, b: 2, c: 3, d: 4, e: 5 };
const obj2 = { a: 1, b: 2, c: 3, d: 4, e: 5 };
// Shallow сравнение проверяет каждое свойство один раз
// O(n) где n - количество свойств
// Обычно это очень быстро для небольших объектов
// Глубокое сравнение было бы:
// O(n * m) где m - средняя глубина
// Значительно медленнее
Лучшие практики
- Используй PureComponent для оптимизации компонентов, которые часто перерисовываются
- Остерегайся новых объектов/массивов — используй useMemo/useCallback
- Помни о shallow сравнении — вложенные объекты сравниваются по ссылке
- Для функциональных компонентов используй React.memo вместо PureComponent
- Профилируй перед оптимизацией — не оптимизируй без необходимости
- Используй custom компаратор в memo если shallow сравнения недостаточно
PureComponent — мощный инструмент, но требует понимания shallow сравнения и правильного управления ссылками на объекты и массивы.