7 best libraries for building lightning fast ReactJS apps
Some essential tools for a rock-star developer
Hello, Habr. As part of the recruitment for the course “React.js Developer“ prepared a translation of the material.
We invite everyone to an open demo lesson “Webpack and babel”… In this lesson, we will look at modern and powerful JavaScript chips – Webpack and Babel. Let’s walk you through how to create a React project from scratch using Webpack. Join us!
ReactJS has high performance by default. But from time to time you have a chance to make it even better. And the wonderful React community has come up with some fantastic libraries for that.
Today we’re going to talk about seven such libraries that can improve the quality of your code while improving performance.
Let’s start.
… … …
1. React Query
It is known that React Query, a state management library for React is missing.
IN documentation it says, “Get, cache, and update data in your React apps without affecting any ‘global state’.”
Yes. This is exactly what she does. It helps us manage the state of the server without the hassle. This can reduce the need to use a state management library like Redux.
Benefits
Automatic caching
Automatic data refresh in the background
Dramatically reduces the amount of code
Before using React Query
Here’s an example for getting data using our custom hook. It doesn’t even support caching.
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}
}
After (using) React Query
Here is the code if we want to use React Query. Look how small it is.
import { useQuery } from 'react-query'
const { isLoading, error, data } = useQuery('repoData', () =>
fetch(url).then(res =>res.json()
)
)
See how much our code has shrunk.
… … …
2. React Hook Form
React Hook Form is a state-of-the-art form handling library that can take your form’s performance to a whole new level.
Benefits
Reduces the amount of code
Reduces unnecessary re-rendering.
Seamlessly integrates with modern user interface (UI) libraries
Below is an example demonstrating how React Hook Form can improve code quality.
No React Hook Form
Here’s an example of how to manually create a login 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>
);
}
With React Form
Here’s the same example with 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>
);
}
It looks neat and effective at the same time. Try it.
… … …
3. React Window
React Window used for rendering long lists. Imagine you have a list of 1,000 items. Only ten are displayed on the screen, but your code is trying to render 1000 items at a time.
This can lead to serious delays in your application. This library is very popular and is a must-have tool in your arsenal.
Hand-rendered 1,000 items
import React, {useEffect, useState} from 'react';
const names = [] // 1000 names
export const LongList = () => {
return <div>
{names.map(name => <div> Name is: {name} </div>)}
<div/>
}
But this code renders 1000 elements at the same time, although you can see no more than 10-20 elements on the screen.
Using React Window
Now let’s use 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>
);
This code only renders what you see on the screen. This may be confusing at first, but necessary if you need to display a long list.
… … …
4. React LazyLoad
Lazy loading is a technique used to download only what you need. Thus, it improves performance without wasting unnecessary computing power.
React LazyLoad is a library specially created for this purpose. You just wrap your component and this library will take care of the rest.
Benefits
Increased productivity
Supports server side rendering
Without LazyLoad
Here’s an example where we load five images manually.
import React from 'react';
const ImageList = () => {
return <div>
<img src="https://habr.com/ru/company/otus/blog/559672/image1.png" />
<img src="image2.png" />
<img src="image3.png" />
<img src="image4.png" />
<img src="image5.png" />
</div>
}
With LazyLoad
Here’s the same example with the LazyLoad component.
import React from 'react';
import LazyLoad from 'react-lazyload';
const ImageList = () => {
return <div>
<LazyLoad> <img src="https://habr.com/ru/company/otus/blog/559672/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
Unnecessary rendering can hurt the performance of your React applications. But sometimes we do it without even knowing it.
This wonderful package, Why did you render, helps us find performance issues and fix them. You just include it in any component and it tells you exactly why the rendering is happening.
Below is a component with rendering issues.
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
Once enabled, this library will write the following output to the console.
It can be seen from this log that we are updating the object with the same value, which is bad for performance.
… … …
6. Reselect
If you are using Redux, then this function will be a lifesaver for you. We know that Redux reducers can store a large amount of data, and if you pass the entire store to a component, it will cause it to be re-rendered every time something in that store is updated.
Reselect solves this problem by memorizing the values and passing only what is needed.
Benefits (from documentation)
Selectors can evaluate derived data, which allows Redux to keep state as little as possible.
Selectors are efficient. The selector is not recalculated if one of its arguments has not changed.
Selectors are compound. They can be used as input to other selectors.
Example
Below is an example of getting values from storage and changing them in a selector.
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 is a well-known library that can be used for comparison. It is very convenient. Indeed, in JavaScript, although two objects can have the same value, they are considered different because they point to different areas of memory.
This is why we see the following result.
const user1 = {
name:'faisal'
}
const user2 ={
name:'faisal'
}
const normalEqual = user1 === user2 // false
But if you need to check equality (for memoization), then it becomes a costly (and difficult) operation.
If we use Deep equal, then this improves performance in 46 times… Below is an example of how we can do this.
var equal = require('deep-equal');
const user1 = {
name:'faisal'
}
const user2 ={
name:'faisal'
}
const deepEqual = equal(user1 , user2); // true -> exactly what we wanted!
… … …
This is what it looks like. These are some of the most important libraries you can use to get the best performance out of your React application.
Leave comments if you have others in mind. Have a nice day!
Resources
Learn more about the course “React.js Developer“
Watch an open online lesson “Webpack and babel”