Categories: Softwares

Оптимизация React компонентов – DEV Community

[ad_1]

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

В этой статье, мы разберем 5 практических способов оптимизации производительности:

  • Мемоизация с помощью использования useMemo() и UseCallback() хуков
  • Оптимизация обращений к API с помощью React Query
  • Оптимизация селекторов с помощью Reselect
  • Заменить useState() на useRef()
  • Использование React Fragments

1. Мемоизация с помощью использования useMemo() и useCallback() хуков

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

Из коробки React предлагает два способа мемоизации:

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

useMemo()

Разберем механизм работы useMemo, на примере умножения двух чисел:

const multiply = (x,y) => 
  return x*y

Enter fullscreen mode

Exit fullscreen mode

multiply — перерасчитывает результат на каждый вызов функции, следовательно компонент каждый раз будет перерисован, не смотря на то что входные параметры функции не изменились. Но если мы используем хук useMemo(), то сможем избежать излишних рендеров, если входные параметры не изменятся и результат вызова функции будет в кэше.

const cachedValue = useMemo(() => multiply(x, y), [x, y])
Enter fullscreen mode

Exit fullscreen mode

В данном случае результат выполнения функции multiply содержится в переменной cachedValue и функция multiply не будет вызываться повторно, до тех пор пока не изменятся входные параметры.

useCallback

useCallback() использует мемоизацию. Отличительная особенность от useMemo() заключается в том, что useCallback() не кэширует результат, вместо этого мемоизирует переданную функцию обратного вызова.

Для примера возьмем компонент с «кликабельным» списком:


import  useCallback  from 'react';
export const ClickableListWithMemoization = ( term ) => 
  const onClick = useCallback(event => 
    console.log('Clicked Item : ', event.currentTarget);
  , [item]);

  return (
    <Listitem=item onClick=onClick />
  );

Enter fullscreen mode

Exit fullscreen mode

В вышеизложенном примере useCallback() мемоизирует функцию обратного вызова onClick, переданную обработчику событий, поэтому компонент не будет вызывать новые рендеры при клике на один и тот же элемент списка.


2. Оптимизация обращений к API с помощью React Query

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

Решением данной проблемы будет использовании библиотеки React Query записывающей в кэш ответ асинхронного вызова. Когда мы делаем запрос к API, React Query сравнит данные из кэша с данными полученными от сервера и в случае отсутствия изменений предотвратит повторный рендеринг компонента.

import React from 'react'
import useQuery from 'react-query'
import axios from 'axios'

async function fetchArticles()
  const data = await axios.get(URL)    
  return data


export const Articles = () => 
  const data, error, isError, isLoading  = useQuery('articles', fetchArticles)

  if(isLoading)
    return <div>Loading...</div>
  

  if(isError)
    return <div>Error! error.message</div>
  

  return(
    <div>
      ...
    </div>
  )

Enter fullscreen mode

Exit fullscreen mode

На момент написания статьи ReactQuery имеет 1000000+ еженедельных скачиваний через npm и больше 28 тысяч звезд на github.


3. Оптимизация селекторов с помощью Reselect

Reselect — сторонняя библиотека для создания мемоизированных селекторов, которая позволяет уменьшить количество повторных рендеров React компонентов.

Чаще всего используется в связке с библиотекой Redux и по умолчанию включена в официальную библиотеку Redux Toolkit.

Создать селектор с помощью Reselect, можно с помощью функции createSelector:

import  createSelector  from 'reselect' 

const selectValue = createSelector(
  state => state.values.value1,
  state => state.values.value2,
  (value1, value2) => value1 + value2
)
Enter fullscreen mode

Exit fullscreen mode

В примере выше функция createSelector создает селектор, который не будет вычислять новое значение, пока входные данные не изменятся.

Библиотека React Query имеет 4000000+ скачиваний через npm и больше 18 тысяч звезд на github.


useState() — часто используется для условного рендеринга, однако, в случаях, когда изменения состояния не должно вызывать повторный рендер React компонента, тогда лучше использовать useRef() хук.

const App = () => 
  const [toggle, setToggle] = React.useState(false)
  const counter = React.useRef(0)

  console.log(counter.current++)

  return (
    <button onClick=() => setToggle(toggle => !toggle)> 
      Click 
    </button>
  )


ReactDOM.render(<React.StrictMode><App /></React.StrictMode>, document.getElementById('mydiv'))
Enter fullscreen mode

Exit fullscreen mode

Повторный рендер не происходит при изменении переменной counter, поскольку useRef() возвращает изменяемый (мутабельный) объект, который будет сохраняться в течении всего жизненного цикла компонента.

Подробнее можно прочитать в официальной документации React.


Каждый React компонент должен возвращать один родительский элемент. Используйте React Fragments для того, чтобы вернуть несколько элементов.

render() 
  return (
    <React.Fragment>
      Какой-то текст.
      <h2>Заголовок</h2>
    </React.Fragment>
  );

Enter fullscreen mode

Exit fullscreen mode

Используйте сокращенный синтаксис <></> для создания фрагментов.


render() 
  return (
    <>
      Какой-то текст.
      <h2>Заголовок</h2>
    </>
  );

Enter fullscreen mode

Exit fullscreen mode

React Fragments не создает DOM элемент, что позволяет ускорить рендеринг и сэкономить память.


Заключение

Большая часть вышеизложенных методов использует кэширование и реализованы через React хуки или сторонние библиотеки. Эти способы улучшают работу вашего приложения уменьшая колличество нежелательных повторных рендеров и уменьшая нагрузку на память.

Спасибо за прочтение! Напишите, если статья была полезной, любая критика приветствуется.

Christine Carter

Recent Posts

How To Choose the Right Sales Automation Solution

In the relentless pace of today's business landscape, where time is money and efficiency is… Read More

1 day ago

Benefits of Group Dog Training: Why Socializing Your Pup Matters

When it comes to raising a well-rounded and well-behaved canine companion, socialization plays a crucial… Read More

2 days ago

All Characters Who Trained Luke Skywalker

Luke Skywalker, the legendary Jedi Knight who ignited a new hope in the galaxy, didn't… Read More

3 days ago

Top 8 Tips to Find the Best Dental Clinic in Dubai [2024]

When it comes to your dental health, choosing the right clinic is crucial for receiving… Read More

1 week ago

Essentials for Effective Multifamily Marketing

In the dynamic world of real estate, multifamily properties present unique marketing challenges and opportunities.… Read More

3 weeks ago

How Couples Salsa Classes Can Strengthen Your Relationship

In the bustling world we inhabit, finding meaningful ways to connect with our partners can… Read More

3 weeks ago