Speed Up ⚡ your React app with these Techniques
Tags: javascript, beginners, react, programming
Published: 2023-03-12 13:54:24

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

```jsx
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>
)

}
```

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()`

```jsx
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>
)

}
```

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

```jsx
import About from "./About"
```

You would import it with lazy loading like

```jsx
import { lazy } from "react"

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

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

```jsx
import { lazy, Suspense } from "react"

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

export default function App(){

return(

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

    <About/>
    
</Suspense>

)

}
```

### 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 }`

```jsx
import { createSelector } from "reselect"
```

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()`
```jsx
import React from "react"

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

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

}
```

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