Master React Optimization Technique

thisisarkajitroy

Arkajit Roy

Posted on May 18, 2024

Master React Optimization Technique

In today's fast-paced web landscape, a React application's performance is paramount. A sluggish app can lead to frustrated users and lost conversions. Fortunately, React provides a plethora of built-in features and libraries to streamline your application and deliver a seamless experience. Here are 7 optimization techniques that will elevate your React app to production-grade quality

01. Component Memoization

To achieve memoization we can employee React.memo which is a higher-order component (HOC) that prevents unnecessary re-renders of functional components by memoizing the component output based on its props. It re-renders only if the props or the component's state change.

import React from 'react';

const MyComponent = React.memo(({ value }) => {
  console.log('Rendered');
  return <div>{value}</div>;
});

export default MyComponent;

Enter fullscreen mode Exit fullscreen mode

Using useCallback and useMemo for Stable Reference

Similar to useMemo but for functions, useCallback prevents unnecessary function recreation when its dependencies haven't changed. This is particularly helpful for callback functions passed as props.

import React, { useCallback, useMemo, useState } from 'react';

const MyComponent = ({ items }) => {
  const [count, setCount] = useState(0);

  const calculateTotal = useMemo(() => {
    return items.reduce((total, item) => total + item.price, 0);
  }, [items]);

  const increment = useCallback(() => {
    setCount((prevCount) => prevCount + 1);
  }, []);

  return (
    <div>
      <p>Total: {calculateTotal}</p>
      <button onClick={increment}>Increment: {count}</button>
    </div>
  );
};

export default MyComponent;

Enter fullscreen mode Exit fullscreen mode

02. Code Splitting Technique

Lazy loading allows you to load components or modules only when they're needed. This reduces the initial bundle size and improves load times, especially for complex applications. React's built-in React.lazy and Suspense components facilitate this process.

import React, { lazy, Suspense } from 'react';

const MyLazyComponent = lazy(() => import('./MyLazyComponent'));

function MyComponent() {
  return (
    <div>
      <button onClick={() => import('./MyLazyComponent')}>Load Lazy Component</button>
      <Suspense fallback={<div>Loading...</div>}>
        <MyLazyComponent />
      </Suspense>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

03. Efficient Event Handling

For frequently triggered events, consider Throttling or debouncing techniques to reduce the number of function calls. Throttling ensures the function executes at most once within a specified time interval, while debouncing only executes it after a period of inactivity.

Debouncing

import React, { useState } from 'react';
import { debounce } from 'lodash';

const Search = () => {
  const [query, setQuery] = useState('');

  const handleSearch = debounce((event) => {
    setQuery(event.target.value);
    // Perform search operation
  }, 300);

  return <input type="text" onChange={handleSearch} />;
};

export default Search;
Enter fullscreen mode Exit fullscreen mode

Throttling

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

const AnimationComponent = () => {
  const ref = useRef();

  useEffect(() => {
    const animate = () => {
      // Update animation frame
      requestAnimationFrame(animate);
    };
    requestAnimationFrame(animate);
  }, []);

  return <div ref={ref}>Animating...</div>;
};

export default AnimationComponent;
Enter fullscreen mode Exit fullscreen mode

04. Rendering Long Lists (Virtualized Lists)

When dealing with extensive lists, list virtualization becomes crucial. It renders only the visible items on the screen, significantly improving performance and reducing DOM manipulation. Popular libraries like react-window and react-virtualized offer efficient solutions

import React from 'react';
import { FixedSizeList as VirtualizedList } from 'react-window';

const ListItem = ({ index, style }) => (
  <div style={style}>Row {index}</div>
);

const MyList = ({ items }) => (
  <VirtualizedList
    height={150}
    itemCount={items.length}
    itemSize={35}
    width={300}
  >
    {ListItem}
  </VirtualizedList>
);

export default MyList;
Enter fullscreen mode Exit fullscreen mode

05. Track Performance Bottlenecks

Profiling is the cornerstone of optimization. Use React DevTools Profiler to identify performance bottlenecks in your components. It pinpoints areas consuming excessive rendering time, guiding your optimization efforts.

import React, { Profiler } from 'react';

const onRenderCallback = (
  id, // the "id" prop of the Profiler tree that has just committed
  phase, // either "mount" (if the tree just mounted) or "update" (if it re-rendered)
  actualDuration, // time spent rendering the committed update
  baseDuration, // estimated time to render the entire subtree without memoization
  startTime, // when React began rendering this update
  commitTime, // when React committed this update
  interactions // the Set of interactions belonging to this update
) => {
  console.log('Render time:', actualDuration);
};

const App = () => (
  <Profiler id="App" onRender={onRenderCallback}>
    <MyComponent />
  </Profiler>
);

export default App;
Enter fullscreen mode Exit fullscreen mode

06. Optimize Context Usage

Using useContextSelector from the use-context-selector library can help in avoiding unnecessary re-renders when using context.

import React from 'react';
import { useContextSelector } from 'use-context-selector';

const CountContext = React.createContext();

const Display = () => {
  const count = useContextSelector(CountContext, state => state.count);
  return <div>{count}</div>;
};

const App = () => {
  const [count, setCount] = React.useState(0);
  const contextValue = { count, setCount };

  return (
    <CountContext.Provider value={contextValue}>
      <Display />
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </CountContext.Provider>
  );
};

export default App;
Enter fullscreen mode Exit fullscreen mode

07. Usage of Fragment Components

Avoid unnecessary DOM nodes by wrapping JSX elements with React.Fragment. This prevents creating extra

elements for layout purposes.
import React, { Fragment } from 'react';

function MyComponent() {
  return (
    <Fragment>
      <p>Item 1</p>
      <p>Item 2</p>
    </Fragment>
  );
}

// OR

function MyComponent() {
  return (
    <>
      <p>Item 1</p>
      <p>Item 2</p>
    </>
  );
}
๐Ÿ’– ๐Ÿ’ช ๐Ÿ™… ๐Ÿšฉ
thisisarkajitroy
Arkajit Roy

Posted on May 18, 2024

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

Sign up to receive the latest update from our blog.

Related

ยฉ TheLazy.dev

About