← Назад к вопросам

Что влияет на рендер компонента?

2.3 Middle🔥 201 комментариев
#React

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что влияет на рендер компонента

Рендер компонента в React — это критическое понимание для оптимизации производительности. Давайте разберёмся, какие факторы влияют на этот процесс.

Основные триггеры рендера

1. Изменение props

Когда родитель передаёт новые props, компонент автоматически перерендеривается. Это происходит даже если значения не изменились, но ссылка на объект другая.

function User({ name, age }) {
  return <div>{name}, {age} лет</div>;
}

// Если родитель рендерит:
<User name="Иван" age={30} /> // новый рендер
<User name="Иван" age={30} /> // еще новый рендер (другие props объекты)

2. Изменение state

Вызов setter функции из useState всегда ведёт к рендеру, даже если значение логически не изменилось.

function Counter() {
  const [count, setCount] = useState(0);
  
  const increment = () => {
    setCount(count + 1); // триггер рендера
  };
  
  return <button onClick={increment}>Счётчик: {count}</button>;
}

3. Контекст (Context API)

Когда значение Context изменяется, все компоненты, которые его используют через useContext, перерендеривают.

const ThemeContext = createContext();

function App() {
  const [theme, setTheme] = useState("light");
  
  return (
    <ThemeContext.Provider value={theme}>
      <Header /> {/* перерендер */}
      <Main />   {/* перерендер */}
      <Footer /> {/* перерендер */}
    </ThemeContext.Provider>
  );
}

4. Рендер родителя

Классическая проблема: если родитель перерендеривает, все дочерние компоненты тоже перерендеривают (рекурсивно вниз по дереву), независимо от изменения их props.

function Parent() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Счётчик: {count}</button>
      <Child /> {/* перерендер каждый раз, хотя props не меняются */}
    </div>
  );
}

function Child() {
  console.log("Child rendered"); // выведется каждый раз
  return <div>Дитя</div>;
}

Оптимизация рендеров

memo() — мемоизация компонента

Предотвращает рендер, если props не изменились.

const Child = memo(function Child({ name }) {
  console.log("Child rendered");
  return <div>{name}</div>;
});

function Parent() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>Счётчик: {count}</button>
      <Child name="Иван" /> {/* НЕ перерендер, props не меняются */}
    </div>
  );
}

useMemo — мемоизация значения

Кэширует дорогие вычисления.

function ExpensiveComponent({ items }) {
  // Без useMemo вычисляется каждый рендер
  const sorted = items.sort((a, b) => a.id - b.id);
  
  // С useMemo вычисляется только когда items меняются
  const optimized = useMemo(() => {
    return items.sort((a, b) => a.id - b.id);
  }, [items]);
  
  return <div>{optimized.length} элементов</div>;
}

useCallback — мемоизация функции

Стабилизирует ссылку на функцию, помогает избежать рендеров дочерних компонентов.

function Parent() {
  const [count, setCount] = useState(0);
  
  // Без useCallback — новая функция каждый рендер
  const handleClick = () => setCount(count + 1);
  
  // С useCallback — одна функция до изменения зависимостей
  const stable = useCallback(() => {
    setCount(count + 1);
  }, [count]);
  
  return <Child onIncrement={stable} />;
}

Ошибки при оптимизации

Неправильные зависимости

// Бесконечный цикл — функция меняется каждый рендер
const handleClick = useCallback(() => {
  setData(data + 1);
}, []); // ❌ data не в зависимостях

Преждевременная оптимизация

// Часто ненужно
const Component = memo(function Simple() {
  return <div>Hello</div>; // Нет props — нет смысла в memo
});

Батчинг (React 18+)

React 18 автоматически группирует обновления в одну фазу рендеринга.

function Form() {
  const [name, setName] = useState("");
  const [age, setAge] = useState(0);
  
  const handleSubmit = async (e) => {
    e.preventDefault();
    setName("Иван");     // батч
    setAge(30);          // батч
    // Один рендер вместо двух
    
    await post("/save");
    setStatus("saved");  // отдельный рендер (асинхронное событие)
  };
  
  return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}

Ключ вывод

Рендер компонента — это не плохо, это просто часть жизненного цикла React. Оптимизируйте только узкие места, проверяйте с React DevTools Profiler, и помните: правильная архитектура (разделение состояния) часто лучше, чем микро-оптимизации.

Что влияет на рендер компонента? | PrepBro