Библиотека 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.
Читайте также:
- Знакомство с ReactJS на базовом уровне
- Почему пора завязывать с React
- 6 актуальных советов по созданию чистого кода React
Читайте нас в Telegram, VK и Яндекс.Дзен
Перевод статьи Mohammad Faisal: Top 7 Libraries for Blazingly Fast ReactJS Applications