Speed Up ⚑ your React app with these Techniques

techwithmanuel

Emmanuel Alozie

Posted on March 12, 2023

Speed Up ⚑ your React app with these Techniques

When building my startup MVPs I'm usually in a constant dilema of using a faster framework, but the community keeps me tied with React and I love speed so here are the techniques I use to speed up my React apps.

1. Replace your useState for useRef in form elements

Observe this piece of code

import {useState} from "react"

export default Function App(){
const [email, setEmail] = useState<string>("")
const [password, setPassword] = useState<string>("")

function handleSubmit(e){
e.preventDefault()
console.log(email, password)
}

return (
<form onSubmit={handleSubmit}>

<input type="text" id="email" value={email} onChange={(e) => setEmail(e.target.value)}/>

<input type="text" id="password" value={password} onChange={(e) => setPassword(e.target.value)}/>

<button type="button">Submit Me</button>

</form>
)

}
Enter fullscreen mode Exit fullscreen mode

You're probably familiar with this and wondering what's wrong with it, but using useState can cause unecessary re-renders, and the useState values aren't used anywhere else than in the handleSubmit() function

So we don't really care what the value of these variables are as they change. So we can make this more efficient using useRef()

import {useRef} from "react"

export default Function App(){
const email = useRef<string>("")
const password = useRef<string>("")

function handleSubmit(e){
e.preventDefault()
console.log(email.current.value, password.current.value)
}

return (
<form onSubmit={handleSubmit}>

<input type="text" id="email" ref={email}/>

<input type="text" id="password" ref={password}/>

<button type="button">Submit Me</button>

</form>
)

}
Enter fullscreen mode Exit fullscreen mode

Once you've made this change, you'll notice that as you enter the fields for the variables, your component will not re-render everytime the state is updated and the functionality remains the same.

2. Windowing

A common requirement for websites is to display a list of data that may scroll up or down, but rendering a large set of data will significantly degrade you application's performance and this could freeze or crash the browser on slower devices

A great technique is virtualization or windowing which is a technique to render only the items that are visible to the user

For example a 1000 todos need to be loaded, we can choose to render a small amount of items that fits on that window, until you scroll to see the rest of the items

For better user experience you can implement scrolling indicators and loaders and the good news is that you don't have to implement them yourself there are libraries that are designed to help you with this namely;

  • react-window
  • react virtualized

But if you are feeling daring, you can also implement your own solutions, but i would not recommend this.

3. React Suspense and Lazy Loading

Lazy loading is an efficient way to render and speed up your application, the idea is to load a component only when it's needed.

You don't need to install any extra dependencies for this, React comes with the lazy API right out of the box so you can render a dynamic import as a regular component

So Instead of importing your app like this

import About from "./About"
Enter fullscreen mode Exit fullscreen mode

You would import it with lazy loading like

import { lazy } from "react"

const About = lazy(() => import('./About'))
Enter fullscreen mode Exit fullscreen mode

To cut down the risk of performance bottlenecks if your app has alot of pages.

A lazy component is typically rendered inside a <Suspense></Suspense>component which allows you to add a fallback UI, while React is fetching you lazy loaded component

import { lazy, Suspense } from "react"

const About = lazy(() => import('./About'))

export default function App(){

return(

<Suspense fallback={<div>Loading... </div>} >

    <About/>

</Suspense>

)

}
Enter fullscreen mode Exit fullscreen mode

4. Memoize Store

Frequent iteraction with a store to retrieve the same data is redundant and unecessary. Memoization is a technique that is often applied to the application but it can also be applied to state management systems like

  • Redux
  • Recoil
  • MobX

For example the reselect library exports { createSelector }

import { createSelector } from "reselect"
Enter fullscreen mode Exit fullscreen mode

That would generate a memoized selector functions, these functions will remember the last values from when they were first invoked and doesn't recalculate if objects are the same.

The re-reselect library takes this futher is deeper memoization and caching is required. It solves the problem of the regular reselect library having only a cache limit of one, and switching between different arguments causes cache invalidation

They both offer great solutions but you have to choose which best soothes you application. To recap

  • reselect - single cache
  • re-reselect - multi cache

5. Avoid Unnecessary Re-renders

When a component re-renders react will also re-render it's children component by default and on larger applications this can slow it down and make the user experience and seo bad, nobody wants a laggy website

On functional components we can avoid this by using useMemo()

import React from "react"

const ListItem = React.memo({item}) => {

return {
     <ul>
          <li>{item}</li>
     </ul>
}

}
Enter fullscreen mode Exit fullscreen mode

This ensures the component is only re-rendered when it's props change.

6. Keep State Local

Keeping the state local to the component will always be faster than using a state management library. My recommendation is use the state management libraries sparing and alternate to using hooks and keeping the state local.

Twitter knows this all too well and this opimization reduced their over head by 50% (86ms)

7. Use web workers

Javascript is a single-threaded programming language meaning you can do only one thing at once.

Web workers make it possible to run a process in web applications background thread separate from the single execution thread, meaning our application and achieve parallel compute without being blocked or slowed down by another function.

Thanks for reading πŸŽ‰, follow βž• for more

πŸ’– πŸ’ͺ πŸ™… 🚩
techwithmanuel
Emmanuel Alozie

Posted on March 12, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

JavaScript Primitive Data Types
javascript JavaScript Primitive Data Types

April 1, 2024

Destructuring in JS
javascript Destructuring in JS

September 19, 2023

Using React "States"
javascript Using React "States"

February 16, 2023

What is react ?
javascript What is react ?

October 26, 2022