7 лучших библиотек для создания эффективных приложений ReactJS

Библиотека ReactJS выделяется своей производительностью. Но теперь у нас появилась возможность еще больше ее усовершенствовать. Сообщество пользователей React создало несколько дополнительных весьма эффективных библиотек.

Рассмотрим семь из них. Они сделают код приложения более совершенным и производительным.

1. React Query

Известно, что React Query  —  это React-библиотека управления состоянием. Согласно ее описанию, она позволяет извлекать, кэшировать и обновлять данные в приложениях React, не затрагивая “глобальное состояние”.

Это действительно так: библиотека позволяет без проблем управлять состоянием сервера. Она даже может сократить необходимость обращения к такой библиотеке управления состоянием, как Redux.

Достоинства:

  • автоматическое кеширование;
  • автоматическое обновление данных в фоновом режиме;
  • значительное сокращение кода.

Без React Query

Вот пример выборки данных с помощью пользовательского хука. Здесь нет даже поддержки кеширования.

const useFetch = (url) => {
  const [data, setData] = useState();
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(false);
 
  useEffect(() => {
    const fetchData = async () => {
      setIsError(false);
      setIsLoading(true);
      try {
        const result = await fetch(url);
        setData(result.data);
      } catch (error) {
        setError(error);
      }
      setIsLoading(false);
    };
    fetchData();
  }, [url]);
  
  return {data , isLoading , isError}
}

С React Query

Вот так сократился код после обработки React Query.

import { useQuery } from 'react-query'

const { isLoading, error, data } = useQuery('repoData', () =>
    fetch(url).then(res =>res.json()
  )
)

2. React Hook Form

React Hook Form  —  это современная библиотека для обработки форм, позволяющая вывести производительность создаваемой формы на совершенно новый уровень.

Достоинства:

  • сокращает код;
  • уменьшает ненужный повторный рендеринг;
  • легко интегрируется с современными библиотеками пользовательского интерфейса (UI).

Следующий пример демонстрирует возможности React Hook Form.

Без React Hook Form

Это пример создания формы входа вручную.

function LoginForm() {
  const [email, setEmail] = React.useState("");
  const [password, setPassword] = React.useState("");

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    console.log({email, password});
  }
  
  return (
    <form onSubmit={handleSubmit}>
    
      <input
        type="email"
        id="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
      />
      
      <input
        type="password"
        id="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
      />
      
    </form>
  );
}

С React Hook

Тот же пример с React Hook Form.

function LoginForm() {
  const { register, handleSubmit } = useForm();
  
  const onSubmit = data => console.log(data);
   
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <input {...register("email")} />
      <input {...register("password")} />
      <input type="submit" />
    </form>
  );
}

Попробуйте  —  код получается чистым и производительным.

3. React Window

React Window используется для отображения длинных списков. Представьте список из 1000 элементов. Одновременно видны только десять из них, но код программы пытается отобразить все 1000 одновременно.

Это может привести к серьезным сбоям в работе приложения. React Window очень популярная библиотека и незаменимый инструмент в арсенале разработчика.

Ручной рендеринг 1000 элементов

import React, {useEffect, useState} from 'react';

const names = [] // 1000 names

export const LongList = () => {

    return <div> 
      {names.map(name => <div> Name is: {name} </div>)} 
    <div/>
}

Этот код отображает 1000 элементов одновременно, хотя на экране видно не более 10–20 элементов.

Используем React Window

import { FixedSizeList as List } from 'react-window';
 
const Row = ({ index, style }) => <div style={style}> Name is {names[index]}</div>
 
const LongList = () => (
  <List
    height={150}
    itemCount={1000}
    itemSize={35}
    width={300}
  >
    {Row}
  </List>
);

Этот код выполняет рендеринг только видимой на экране части списка. Сначала такое решение может показаться опасным, но оно необходимо для рендеринга длинных списков.

4. React LazyLoad

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

Именно с этой целью и создана библиотека React LazyLoad. Нужно просто указать компонент, а библиотека сделает все остальное.

Достоинства:

  • улучшенная производительность;
  • поддержка рендеринга на стороне сервера.

Без LazyLoad

import React from 'react';

const ImageList = () => {
  
  return <div>
    <img src ='image1.png' />
    <img src ='image2.png' />
    <img src ='image3.png' />
    <img src ='image4.png' />
    <img src ='image5.png' />
  </div>
}

В этом примере вручную загружаются пять изображений.

С LazyLoad

Тот же пример, но с использованием LazyLoad.

import React from 'react';
import LazyLoad from 'react-lazyload';

const ImageList = () => {
  
  return <div>
    <LazyLoad> <img src ='image1.png' /> <LazyLoad>
    <LazyLoad> <img src ='image2.png' /> <LazyLoad>
    <LazyLoad> <img src ='image3.png' /> <LazyLoad>
    <LazyLoad> <img src ='image4.png' /> <LazyLoad>
    <LazyLoad> <img src ='image5.png' /> <LazyLoad>
  </div>
}

5. Пакет Why Did You Render

Излишний рендеринг может негативно сказаться на производительности приложений React. Но об этом иногда даже не подозревают.

Выявлять и решать проблемы с производительностью помогает пакет Why Did You Render. Он просто включается в любой компонент и точно сообщает причины рендеринга.

Ниже приведен компонент с проблемами рендеринга.

import React, {useState} from 'react'

const WhyDidYouRenderDemo = () => {
    console.log('render')
    
    const [user , setUser] = useState({})
    const updateUser = () => setUser({name: 'faisal'})

    return <>
        <div > User is : {user.name}</div>
        <button onClick={updateUser}> Update </button>
    </>
}

export default WhyDidYouRenderDemo

После включения эта библиотека будет регистрировать на консоли следующие выходные данные.

Причина рендеринга

Из журнала регистрации видно, что объект обновляется с прежним значением. А это плохо отражается на производительности.

6. Reselect

Эта библиотека  —  спасательный круг для тех, кто использует Redux. Известно, что редукторы Redux могут хранить много данных. Если вводить в любой компонент полный массив данных, то после любого его частичного обновления будет выполняться повторный рендеринг.

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

Достоинства

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

Пример

Ниже приведен пример получения значений из массива данных и модификации их в селекторе.

import { createSelector } from 'reselect'

const shopItemsSelector = state => state.shop.items

const subtotalSelector = createSelector(
  shopItemsSelector,
  items => items.reduce((subtotal, item) => subtotal + item.value, 0)
)

const exampleState = {
  shop: {
    items: [
      { name: 'apple', value: 1.20 },
      { name: 'orange', value: 0.95 },
    ]
  }
}

7. Deep Equal

Deep Equal  —  известная библиотека, которую удобно использовать для сравнения. Несмотря на то, что два объекта JavaScript могут иметь одинаковые значения, они считаются разными, если хранятся в разных ячейках памяти. Поэтому получаем следующий результат.

const user1 = {
    name:'faisal'
}
const user2 ={
    name:'faisal'
}

const normalEqual = user1 === user2 // false

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

Использование Deep Equal повышает производительность в 46 раз. Пример тому представлен ниже.

var equal = require('deep-equal');

const user1 = {
    name:'faisal'
}
const user2 ={
    name:'faisal'
}

const deepEqual = equal(user1 , user2); // true -> exactly what we wanted!

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

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Перевод статьи Mohammad Faisal: Top 7 Libraries for Blazingly Fast ReactJS Applications

Предыдущая статьяИсследование данных - основные понятия
Следующая статья7 визуальных элементов в дизайне