REACT HOOKS — useMemo()

Что такое хук useMemo

Хук useMemo() используется для предотвращения дорогостоящих вычислений при каждом рендере путем использования мемоизации.

UseMemo() возвращает мемоизированное значение только при изменении его зависимостей.

Что такое мемоизация

Мемоизация — это техника оптимизации. Она используется для ускорения работы компьютерной программы/компонента путем сохранения результата дорогостоящей операции и использования сохраненного значения, если результат не изменился.

Если результат дорогостоящей функции не меняется, то он не пересчитывается, а используется сохраненное значение (кэшированное значение).

Оптимизация компонента с помощью хука useMemo()

Давайте рассмотрим пример использования хука useMemo и когда его следует применять.

Сначала нам нужно создать приложение react. Мы можем сделать это с помощью приведенной ниже команды

npx create-react-app myApp

Далее я создал функцию ExpensiveCalculation в одноименном js-файле.

function ExpensiveCalculation(num) {
    console.log("calculating...");
    for (let i = 0; i < 1000000000; i++) {
      num += 1;
    }
    return num;
}

export default ExpensiveCalculation;

Вход в полноэкранный режим Выйти из полноэкранного режима

Приведенная выше функция является дорогой функцией, которая снижает производительность компонента. Приведенная выше функция добавит 1 к num, которое передается в качестве параметра в ExpensiveCalculation.

Цикл for проверяет, если значение i меньше 1000000000, если это так, то 1 будет добавлена к предыдущему значению num, а затем функция вернет обновленное значение num.

Затем я создал компонент AddItems.js в папке src. Давайте посмотрим, как работает компонент без useMemo.

import { useState} from "react";

function AddItems() {
    const [items, setItems] = useState([]);
    const [count, setCount] = useState(1);

    // without memoization --> expensive calculation
    const calculation = ExpensiveCalculation(count)

    const addItems = () => {
        setItems((prev) => [...prev, `New item`]);
    };

    const incrementCount = () => {
        setCount((c) => c + 1);
    };

    return (
        <div>
            {items.map((item) => (
                <li>{item}</li>
            ))}
            <button onClick={addItems}>Add items</button>
            <div style={{ display: "flex" }}>
                <h2>Expensive Calculation</h2>
                <button onClick={incrementCount}>calculate</button>
                {calculation}
            </div>
        </div>
    );
}

export default AddItems;
Вход в полноэкранный режим Выход из полноэкранного режима

ExpensiveCalculation назначается на const расчет. Мемоизация здесь не используется.

Есть кнопка Add Item, которая добавляет новые элементы, и они будут отображаться в браузере.

Есть еще одна кнопка calculate, которая увеличивает count.

Теперь каждый раз, когда мы нажимаем на кнопку calculate, счетчик будет увеличиваться, а счетчик передается в качестве аргумента в ExpensiveCalculation.

const calculation = ExpensiveCalculation(count)

В файле ExpensiveCalculation будет запущен цикл for, который будет проверять, если i меньше 1000000000. Это займет некоторое время, так как 1000000000 — большое значение, поэтому AddItem потребуется время для повторного отображения обновленного значения.

Теперь, когда мы нажмем на кнопку Add Item, ExpensiveCalcution также будет запущен, и компонент AddItem займет больше времени для повторного отображения, несмотря на то, что мы просто хотели добавить новый элемент и отобразить его.

Из-за ExpensiveCalculation происходит задержка в выполнении, и компонент AddItem дольше перерисовывается. Чтобы решить эту проблему производительности, мы воспользуемся хуком useMemo.

Чтобы использовать мемоизацию в react, мы должны импортировать хук useMemo из react

const calculation = useMemo(()=>ExpensiveCalculation(count),[count])
Войти в полноэкранный режим Выйти из полноэкранного режима

Хук useMemo принимает второй параметр для объявления зависимостей. В приведенном выше коде функция ExpensiveCalculation будет вызываться только при изменении счета.

Мы видим, что когда значение счета не изменяется, функция возвращает кэшированное значение, и при нажатии на кнопку добавления элемента не происходит задержки.

Ниже приведен полный код после использования хука useMemo.

import { useState, useMemo } from "react";
import ExpensiveCalculation from "./ExpensiveCalculation";

function AddItems() {
    const [items, setItems] = useState([]);
    const [count, setCount] = useState(1);

    //with useMemo hook
    const calculation = useMemo(() => ExpensiveCalculation(count), [count])

    const addItems = () => {
        setItems((prev) => [...prev, `New item`]);
    };

    const incrementCount = () => {
        setCount((c) => c + 1);
    };

    return (
        <div style={{ display: "flex", displayDirection: "row", gap: "5rem" }}>
            <div>
                {items.map((item, idx) => (
                    <li key={idx}>{item}</li>
                ))}
                <button onClick={addItems}>Add items</button>
            </div>
            <div>
                <h2>Expensive Calculation</h2>
                <button onClick={incrementCount}>calculate</button>
                {calculation}
            </div>
        </div>
    );
}

export default AddItems;
Вход в полноэкранный режим Выход из полноэкранного режима

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

Оцените статью
devanswers.ru
Добавить комментарий