Мемоизация

Мемоизация в Chakra UI — это метод оптимизации производительности компонентов, позволяющий предотвращать лишние перерасчёты стилей и повторный рендеринг элементов, когда их пропсы или состояние не изменились. В контексте React и Chakra UI мемоизация становится особенно важной при работе с динамическими стилями и сложными интерфейсами.


Использование React.memo для компонентов Chakra UI

React.memo — базовый инструмент мемоизации компонентов. Он позволяет оборачивать функциональный компонент и сохранять его результат рендера, если пропсы не изменились.

import { Box, Text } from "@chakra-ui/react";
import React from "react";

const Card = React.memo(({ title, content }) => {
  console.log("Рендер Card");
  return (
    <Box p={4} borderWidth="1px" borderRadius="md">
      <Text fontWeight="bold">{title}</Text>
      <Text>{content}</Text>
    </Box>
  );
});

export default Card;

Ключевые моменты:

  • React.memo сравнивает пропсы по поверхностному равенству.
  • Если пропсы не изменились, компонент не перерисовывается.
  • Для глубоких объектов можно передавать кастомную функцию сравнения через второй аргумент React.memo(Component, areEqual).

Мемоизация стилей с useMemo

Chakra UI активно использует проп sx или объектные стили (style props). При динамических вычислениях стилей важно использовать useMemo, чтобы объект стилей не создавался заново на каждом рендере, что могло бы вызвать лишние перерисовки.

import { Box } from "@chakra-ui/react";
import { useMemo } from "react";

function ColoredBox({ colorMode }) {
  const styles = useMemo(() => ({
    bg: colorMode === "dark" ? "gray.800" : "gray.100",
    p: 4,
    borderRadius: "md",
  }), [colorMode]);

  return <Box {...styles}>Контент</Box>;
}

Пояснения:

  • useMemo возвращает мемоизированный объект стилей.
  • Объект обновляется только при изменении зависимостей (в примере — colorMode).
  • Предотвращает лишние рендеры дочерних компонентов, которые зависят от стилей.

Мемоизация функций с useCallback

В Chakra UI часто передаются колбэки для событий или кастомных хуков. Чтобы функции не создавались заново при каждом рендере, используют useCallback.

import { Button } from "@chakra-ui/react";
import { useCallback } from "react";

function Counter({ onIncrement }) {
  const handleClick = useCallback(() => {
    onIncrement(1);
  }, [onIncrement]);

  return <Button onCl ick={handleClick}>Добавить</Button>;
}

Важно:

  • useCallback возвращает мемоизированную функцию.
  • Использование с React.memo предотвращает ненужный рендер дочерних компонентов.
  • Подходит для функций, передаваемых глубоко в дерево компонентов.

Мемоизация с useColorModeValue

Chakra UI предоставляет хук useColorModeValue, который сам по себе оптимизирован и возвращает значение в зависимости от темы. Но при сложных вычислениях стоит комбинировать его с useMemo.

import { Box, useColorModeValue } from "@chakra-ui/react";
import { useMemo } from "react";

function ThemedBox({ size }) {
  const bg = useColorModeValue("gray.100", "gray.800");

  const styles = useMemo(() => ({
    bg,
    w: size,
    h: size,
    borderRadius: "full",
  }), [bg, size]);

  return <Box {...styles} />;
}
  • useMemo предотвращает пересоздание объекта стилей при каждом рендере.
  • useColorModeValue возвращает актуальное значение темы, безопасно использовать внутри мемоизированных объектов.

Оптимизация списка компонентов

При рендере больших списков Chakra UI компонентов полезно комбинировать React.memo и useMemo для элементов списка.

import { VStack, Text, Box } from "@chakra-ui/react";
import React, { useMemo } from "react";

const Item = React.memo(({ name }) => (
  <Box p={2} borderBottomWidth="1px">
    <Text>{name}</Text>
  </Box>
));

function ItemList({ items }) {
  const renderedItems = useMemo(
    () => items.map((item) => <Item key={item.id} name={item.name} />),
    [items]
  );

  return <VStack>{renderedItems}</VStack>;
}

Особенности:

  • useMemo предотвращает пересоздание массива компонентов при неизменных данных.
  • React.memo предотвращает повторный рендер отдельных элементов.
  • Это особенно важно для динамических списков с сотнями элементов.

Советы по мемоизации в Chakra UI

  • Мемоизация объектов стилей критична при передаче сложных объектов в Box, Flex или кастомные компоненты.
  • Использовать React.memo для часто рендерящихся компонентов с неизменными пропсами.
  • useCallback применим для обработчиков событий и колбэков, чтобы не вызывать повторный рендер дочерних компонентов.
  • useMemo эффективен для вычислений значений, зависящих от пропсов или состояния.
  • Комбинирование хуков мемоизации с useColorModeValue и другими утилитами Chakra UI позволяет создавать высокопроизводительные интерфейсы с динамическими стилями.