Существует ряд встроенных инструментов для повышения производительности приложений React. Одним из таких инструментов является компонент высокого порядка React.memo ()
. Это руководство поможет вам узнать о React.memo ()
. Вы узнаете, что это такое, как работает и как использовать в своих приложениях React.
Содержание статьи
Что такое React.memo ()
Начнем с того, что такое React.memo ()
. Это компонент высокого порядка (HOC). Компонент более высокого порядка — это функция, которая принимает другой компонент и возвращает новый компонент. Вы можете думать о HOC как о оболочке, которая преобразует некоторый компонент, который вы ей передаете, в новый компонент.
Как memo () помогает
React.memo ()
помогает нам повысить производительность приложений React, избегая ненужной визуализации компонентов. Каждый раз, когда React должен решить, обновлять ли DOM, он сравнивает предыдущий рендер с новым. Если эти два рендера различны, некоторые данные отличаются, React повторно визуализирует DOM, чтобы обновить его.
Это сделано для того, чтобы пользовательский интерфейс синхронизировался с данными. Когда это происходит, React повторно визуализирует компоненты, которые в настоящее время отображаются в DOM. Это может занять некоторое время и потреблять некоторые ресурсы, в зависимости от количества визуализированных компонентов. React.memo ()
помогает нам ускорить этот процесс.
Когда мы оборачиваем какой-то компонент с помощью React.memo ()
произойдут три вещи. Во-первых, React отрендерит компонент при первоначальном рендеринге, как обычно. Однако после этого React также запомнит компонент. React сохранит результат этого рендеринга в памяти.
мемо () и мемоизация
Интересная вещь происходит, когда что-то заставляет React повторно визуализировать DOM. На этот раз с memo ()
React не будет автоматически повторно отображать компонент. Вместо этого он проверит, совпадают ли новые свойства компонента с запомненным компонентом из предыдущего рендера.
Если React обнаружит, что свойства компонента не изменились, он будет повторно использовать запомненный результат предыдущего рендеринга и пропустить повторный рендеринг компонента с нуля. React будет в основном повторно использовать «старую» версию компонента. Когда React использует предыдущую версию компонента, он также повторно использует все содержимое этого предыдущего компонента.
Это означает, что если у нас есть какие-то вычисления в этом компоненте, эта компиляция может не повториться, если только это не необходимо, т.е. изменится какой-то внешний ресурс. Это означает, что мы можем избежать не только ненужного повторного рендеринга компонента, но, что более важно, повторения вычислений, которые не нужны внутри этого компонента.
Что, если изменится реквизит компонента? React повторно отрендерит компонент и выполнит внутри него все необходимые вычисления. Это, мемоизация с memo ()
работает только с функциональными компонентами. Однако мы можем добиться этого с помощью компонентов класса, если будем использовать PureComponent.
Как использовать
В React.memo ()
есть одно преимущество: он очень прост в использовании. Все, что нам нужно сделать, это взять какой-то функциональный компонент, который мы хотим запомнить, и обернуть его с помощью memo ()
. Мы можем сделать это с помощью нового компонента, который мы хотим создать, а также с помощью уже существующего компонента.
// Функциональный компонент без memo ():
export const App = () => {
возвращение (
Привет, мир
)
}
// Функциональный компонент с memo ():
// Импортировать заметку из React:
импортировать {memo} из "реагировать"
// Оборачиваем компонент приложения с помощью memo ():
export const App = memo (() => {
возвращение (
Привет, мир
)
})
// Создаем компонент и запоминаем его позже:
// Импортировать заметку из React:
импортировать {memo} из "реагировать"
// Создаем компонент:
const App = () => {
возвращение (
Привет, мир
)
}
// Запоминание и экспорт компонента приложения:
экспорт const AppMemoized = memo (приложение)
Неглубокое сравнение и функция пользовательского сравнения
По умолчанию React выполняет поверхностное сравнение объектов реквизита при сравнении реквизитов из предыдущего рендера и следующего. В большинстве случаев этого будет достаточно, если пропсы, которые вы передаете, простые, то есть примитивные типы данных. Этого может быть недостаточно, если вы работаете со сложным реквизитом.
Например, если вы передаете объекты или массивы через props, поверхностного сравнения, выполненного React, будет недостаточно. React, вероятно, не сможет распознать, что какой-то объект, прошедший через props, такой же, как и предыдущий. Это потому, что когда дело доходит до объектов, React сравнивает ссылки, а не сами объекты.
Это вызовет проблемы с поверхностным сравнением. Допустим, мы создаем новый объект, который будет таким же, как какой-то другой объект. Дело в том, что эти два объекта не будут одинаковыми. Они будут иметь одинаковую форму, будут содержать одинаковые данные, но будут иметь разные ссылки.
Для React и JavaScript, когда дело касается объектов, ссылки более важны. Когда две ссылки различны, поверхностное сравнение не удастся.
// Сравните «одинаковые» объекты:
console.log ({foo: 'foo'} === {foo: 'foo'})
// Выход:
// ложный
// Или:
const obj1 = {foo: 'foo'}
const obj2 = {foo: 'foo'}
console.log (obj1 === obj2)
// Выход:
// ложный
// Сравните «одинаковые» массивы:
console.log ([1] === [1])
// Выход:
// ложный
// Или:
const arr1 = [1]
const arr2 = [1]
console.log (arr1 === arr2)
// Выход:
// ложный
// Используйте ту же ссылку:
const obj1 = {foo: 'foo'}
const obj2 = obj1
console.log (obj1 === obj2)
// Выход:
// правда
const arr1 = [1]
константа arr2 = arr1
console.log (arr1 === arr2)
// Выход:
// правда
Использование пользовательской функции сравнения
К счастью, React позволяет нам использовать настраиваемую функцию сравнения для проверки равенства свойств. Итак, если мы знаем, что нам нужно более тщательное сравнение, мы можем предоставить React.memo ()
пользовательскую функцию сравнения. Эта функция является вторым аргументом сразу после компонента, который мы хотим запомнить.
// Функциональный компонент с memo ():
// Импортировать заметку из React:
импортировать {memo} из "реагировать"
импортировать {isEqual} из lodash
// Создаем настраиваемую функцию сравнения:
function compareProps (prevProps, nextProps) {
return isEqual (prevProps, nextProps)
}
// Обернуть с помощью memo () и использовать пользовательскую функцию сравнения:
export const App = memo (() => {
возвращение (
Привет, мир
)
}, compareProps) // Передаем compareProps как второй аргумент
// Создаем компонент и запоминаем его позже:
// Импортировать заметку из React:
импортировать {memo} из "реагировать"
импортировать {isEqual} из lodash
// Создаем компонент:
const App = () => {
возвращение (
Привет, мир
)
}
// Запоминание с помощью специальной функции сравнения:
export const AppMemoized = memo (App, compareProps) // Передайте compareProps в качестве второго аргумента
Если вы хотите использовать пользовательскую функцию сравнения, помните о двух важных вещах. Во-первых, эта функция всегда должна возвращать логическое значение. Во-вторых, он должен возвращать true
если предыдущие и следующие свойства равны. В противном случае он должен вернуть false
.
Когда использовать памятку ()
У всего есть своя цена. Вот почему, прежде чем пытаться использовать memo ()
по умолчанию, вы должны учесть одну вещь. Когда вы его используете, React сохраняет результат рендеринга компонента в памяти. Если вы решите запоминать большое количество компонентов, это приведет к большему потреблению памяти.
Еще одна вещь, на которую стоит обратить внимание, — это сравнение. Когда React сравнивает предыдущий и следующий реквизиты, ему требуются некоторые ресурсы. Это может быть не так уж важно, если ваше приложение маленькое или у вас не слишком много запоминаемых компонентов. Если вы работаете над большим проектом, повторный рендеринг может оказаться дешевле, чем мемоизация.
Дело в том, что React уже хорошо работает над оптимизацией производительности рендеринга. Итак, прежде чем пытаться запомнить все, профилируйте свое приложение и определите проблемы. Если вы обнаружите, что некоторые компоненты визуализируются, когда в этом нет необходимости, попробуйте использовать React.memo ()
. Затем снова профилируйте свое приложение и сравните результаты.
Повторите этот процесс со всеми компонентами, которые хотите запомнить. Если вы видите какие-то значимые улучшения, сохраните запомненную версию. В противном случае, если улучшения производительности не наблюдается или наблюдается некоторый штраф, просто позвольте компоненту повторно выполнить рендеринг.
Некоторые практические правила
Помимо вышесказанного, есть несколько практических правил, которые могут помочь вам найти компоненты, которые стоит запомнить. Во-первых, ищите компоненты, которые часто перерисовываются, обычно с одними и теми же реквизитами. Это часто случается, когда родительский компонент вынуждает повторно выполнить рендеринг, даже если сам компонент не изменился.
React.memo ()
может помочь вам избежать повторного рендеринга, вызванного родителями. Во-вторых, попробуйте запоминать компонент, если компонент всегда отображает один и тот же результат при одних и тех же свойствах. В-третьих, ваш компонент отрисовывает много пользовательского интерфейса. Чем больше пользовательского интерфейса отрисовывает компонент, тем обычно дороже эти отрисовки.
В этих случаях ресурсов, необходимых для запоминания и проверки сравнения, может быть меньше ресурсов для последующих повторных отрисовок.
Заключение: Начало работы с React.memo ()
React.memo ()
может быть очень полезным инструментом, когда мы хотим улучшить производительность наших приложений React. Это позволяет очень легко запоминать компоненты и избегать ненужного повторного рендеринга. Я надеюсь, что это руководство помогло вам понять, что такое memo ()
как оно работает и как его использовать.
<! —
У вас есть какие-либо вопросы, рекомендации, мысли, советы или подсказки, которыми вы хотели бы поделиться с другими читателями этого блога и со мной? Пожалуйста, поделитесь этим в комментарии. Вы также можете отправить мне письмо. Я хотел бы получить известие от вас.
->
<! —
Хотите еще?
->
Если вам понравилась эта статья, подпишитесь, чтобы не пропустить ни одной публикации в будущем.
<! —
Кроме того, вы можете найти меня на GitHub, Twitter и Dribbble.
->
Если вы хотите поддержать меня и этот блог, вы можете стать его покровителем или купить мне кофе 🙂
Стать покровителем
Пожертвовать через Paypal