Showing posts with label React Components. Show all posts
Showing posts with label React Components. Show all posts

June 12, 2025

Performance Optimization in React: Real-World Examples

Introduction

React is powerful, but it can suffer performance issues when components re-render unnecessarily or handle more work than needed.

This guide explores 6 common performance bottlenecks in real-world applications — along with practical techniques to address them. Each example includes before-and-after code and clear explanations of what’s happening, why it matters, and how to optimize it effectively.


1. Unnecessary Re-renders in Child Components

Consider a simple Counter component that displays a number. Even if only the input field is updated, the Counter still re-renders - a common inefficiency in many apps.

Before Optimization

function Counter({ count }) {
  console.log("Counter rendered");
  return <h2>Count: {count}</h2>;
}

function App() {
  const [count, setCount] = React.useState(0);
  const [text, setText] = React.useState("");

  return (
    <div>
      <Counter count={count} />
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <input value={text} onChange={(e) => setText(e.target.value)} />
    </div>
  );
}

After Optimization (using react-window)

const Counter = React.memo(function Counter({ count }) {
  console.log('Counter rendered');
  return <h2>Count: {count}</h2>;
});

What's happening?
Every time the App component re-renders - even when updating the text input — the Counter component also re-renders.
Why it's a problem?
React re-renders all child components by default, even if their props haven’t changed. This adds up fast in large trees.
Optimization Approach
Use React.memo to prevent unnecessary re-renders by memoizing the component unless its props actually change.

2. Rendering Huge Lists Without Virtualization

Rendering thousands of DOM nodes can completely freeze your browser. If you ever render a long list — this is critical.

Before Optimization

function App() {
  const items = Array.from({ length: 10000 }, (_, i) => `Item ${i}`);

  return (
    <div style={{ height: '400px', overflowY: 'auto' }}>
      {items.map((item) => (
        <div key={item}>{item}</div>
      ))}
    </div>
  );
}

After Optimization (using react-window)

import { FixedSizeList as List } from 'react-window';

function App() {
  const items = Array.from({ length: 10000 }, (_, i) => `Item ${i}`);

  return (
    <List
      height={400}
      itemCount={items.length}
      itemSize={35}
      width={'100%'}
    >
      {({ index, style }) => (
        <div style={style}>{items[index]}</div>
      )}
    </List>
  );
}

What's happening?
All 10,000 list items are rendered and pushed into the DOM at once.

Why it's a problem?
Rendering thousands of DOM nodes is memory-intensive and causes the browser to lag or freeze.

How to fix it?
Use virtualization (react-window) to render only visible items and reuse DOM nodes during scroll. Smooth performance, minimal overhead.


3. Function Re-created on Every Render

Every render creates a new function instance (e.g., the onClick handler in a button). This can cause unnecessary re-renders of child components, especially when they are memorized.

Before Optimization

function App() {
  const [count, setCount] = React.useState(0);
  return <Button onClick={() => setCount(count + 1)} />;
}

After Optimization

const handleClick = React.useCallback(() => {
  setCount((prev) => prev + 1);
}, []);
return <Button onClick={handleClick} />;

What's happening?
The inline arrow function gets recreated every time the component re-renders, so it has a new reference each time.

Why it's a problem?
If the Button component is memoized, it will still re-render because the onClick prop changes by reference.

How to fix it?
Wrap the function in useCallback to keep the reference stable across renders and avoid unnecessary updates downstream.

4. Tab Content Re-renders on Every Switch

Switching between tabs causes all tab content to unmount and remount, losing state and triggering unnecessary re-renders.

Before Optimization

{activeTab === 'profile' && <Profile />}
{activeTab === 'settings' && <Settings />}

After Optimization

const tabs = useMemo(() => ({
  profile: <Profile />,
  settings: <Settings />,
}), []);
return tabs[activeTab];


What's happening?
Each tab component mounts/unmounts when switching, resetting its internal state and triggering re-renders.

Why it's a problem?
Components lose their internal state, and there's a noticeable delay on tab switches due to remounting.

How to fix it?
Store components in `useMemo` and toggle visibility instead of remounting. This keeps the component’s state and makes switching faster.


5. Uncontrolled Component Switching to Controlled

Switching an input from uncontrolled to controlled (e.g., setting its value from undefined to a real value) leads to a React warning and a forced re-render.

Before Optimization

function Input({ value }) {
  return <input value={value} onChange={() => {}} />;
}

When value is initially undefined, this becomes uncontrolled, and when it gets a value, React throws a warning and forces a re-render

After Optimization

function Input({ value }) {
  return <input value={value ?? ''} onChange={() => {}} />;
}

What's happening?
If value starts as undefined, React treats the input as uncontrolled. When it gets a value later, it switches to controlled — and React throws a warning.
Why it's a problem?
Switching from an uncontrolled to a controlled input in React causes the field to reset and displays a warning.
How to fix it?
Use a fallback value (value ?? '') to keep the input controlled from the beginning, avoiding warning and preserving expected behavior.


6. Large Components Doing Too Much

Rendering too many components at once in a large bundle can delay the first paint, making your app feel slow and unresponsive.

Before Optimization

function Dashboard() {
  return (
    <>
      <HeavyChart />
      <LiveFeed />
      <WeatherWidget />
      <NotificationPanel />
    </>
  );
}

All components are rendered and mounted at once.

After Optimization (Code Splitting)

const HeavyChart = React.lazy(() => import('./HeavyChart'));

function Dashboard() {
  return (
    <Suspense fallback={<Loader />}>
      <HeavyChart />
      {/* Other components can load similarly */}
    </Suspense>
  );
}

What's happening?
All dashboard components are loaded upfront, even if they’re not visible or immediately needed.

Why it's a problem?
It bloats the initial JavaScript bundle, slowing down your app's first render and hurting metrics like LCP.

How to fix it?
Use React.lazy with Suspense to load components only when you need them. This helps the app load faster and feel more responsive.


Final Thoughts

Performance issues in React often creep in silently - small inefficiencies that add up as your app grows. These optimization patterns are widely applicable and can help improve performance and user experience across React applications of all sizes.

June 5, 2025

React Hooks vs Class Components: A Beginner-Friendly Comparison

If you’re new to React or have experience with class components, you may have heard that hooks have brought significant changes to the way React applications are developed.

Early in React’s history, class components were the standard approach., class components were everywhere. Managing state, dealing with lifecycle methods like componentDidMount, and passing data using context often felt confusing and repetitive. With the introduction of hooks, React development became simpler and cleaner.

In this blog, I want to walk you through the basics of four important hooks:

  • useState
  • useEffect
  • useRef
  • useContext

For each hook, I’ll show you what code looked like before hooks (using classes) and how much easier it is with hooks. I’ll also explain the pain points and benefits from my perspective.

1. useState: Managing Local Component State

Let’s start with the most used hook - useState.

Without Hooks (Class Component)

class Counter extends React.Component {
    state = { count: 0 };
 
    increment = () => {
      this.setState({ count: this.state.count + 1 });
    };
 
    render() {
      return (
        <div>
          <h3>Count: {this.state.count}</h3>
          <button onClick={this.increment}>Increment</button>
        </div>
      );
    }
  }

With Hook: useState (Function Component)

import React, { useState } from "react";
function Counter() {
    const [count, setCount] = useState(0);
 
    return (
      <div>
        <h3>Count: {count}</h3>
        <button onClick={() => setCount(count + 1)}>Increment</button>
      </div>
    );
  }

What Was Difficult Without Hooks:
  • You had to use this.state, this.setState, and bind functions.
  • Even for small components, you needed a class.
  • State logic wasn’t reusable.

Why useState is Better:
  • Much cleaner and easier to read.
  • No more dealing with this.
  • You can manage multiple states independently in one component.

2. useEffect: Doing Side Effects (e.g. API Calls, Timers)

When your component needs to fetch data, set up a timer, or do something after render - you use useEffect.

Without Hooks (Class Component)

class Timer extends React.Component {
  state = { seconds: 0 };

  componentDidMount() {
    this.interval = setInterval(() => {
      this.setState(prev => ({ seconds: prev.seconds + 1 }));
    }, 1000);
  }

  componentWillUnmount() {
    clearInterval(this.interval);
  }

  render() {
    return <h3>Time: {this.state.seconds} seconds</h3>;
  }
}

With Hook: useEffect(Function Component)

import React, { useEffect} from "react";
function Timer() {
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    const interval = setInterval(() => setSeconds(s => s + 1), 1000);
    return () => clearInterval(interval);
  }, []);

  return <h3>Time: {seconds} seconds</h3>;
}


What Was Difficult Without Hooks:
  • You had to spread your logic across multiple lifecycle methods.
  • It was hard to keep related logic together.
  • Cleanup code (like stopping a timer) was messy.

Why useState is Better:
  • Everything lives in one place.
  • Cleanup is easy with the return function.
  • Execution is controlled by specifying dependencies in the array.


3. useRef: Getting a Reference to a DOM Element or Persistent Value

If you’ve ever needed to directly access an input field or persist a value between renders without triggering a re-render — useRef is the way to go.

Without Hooks (Class Component)

class FocusInput extends React.Component {
  constructor() {
    super();
    this.inputRef = React.createRef();
  }

  focus = () => {
    this.inputRef.current.focus();
  };

  render() {
    return (
      <div>
        <input ref={this.inputRef} type="text" />
        <button onClick={this.focus}>Focus Input</button>
      </div>
    );
  }
}

With Hook: useRef (Function Component)

import React, { useRef} from "react";
function FocusInput() {
    const inputRef = useRef(null);
 
    return (
      <div>
        <input ref={inputRef} type="text" />
        <button onClick={() => inputRef.current.focus()}>Focus Input</button>
      </div>
    );
  }

What Was Hard Without Hooks:

  • You needed constructors and had to manage refs manually.
  • It made the component more complex.

Why useRef is Better:

  • You can declare and use it easily in functional components.
  • It’s perfect for keeping mutable values around without causing re-renders.

4. useContext: Accessing Global Data Easily

When you want to pass down data (like theme or user info) to deeply nested components, useContext is your friend.

Without Hooks (Class Component)

const ThemeContext = React.createContext('light');

class ThemedButton extends React.Component {
  static contextType = ThemeContext;

  render() {
    const theme = this.context;
    return <button style={{ background: theme === 'dark' ? '#333' : '#eee' }}>
             Theme: {theme}
           </button>;
  }
}

With Hook: useContext (Function Component)

import React, { useContext} from "react";
const ThemeContext = React.createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext);
  return <button style={{ background: theme === 'dark' ? '#333' : '#eee' }}>
           Theme: {theme}
         </button>;
}

What Was Hard Without Hooks:

  • You had to use static contextType.
  • It wasn’t easy to use multiple contexts at once.
  • More boilerplate.

Why useContext is Better:

  • Just call useContext in any functional component.
  • Clean and simple syntax.
  • Great for global state like auth, theme, user, etc.

Final Thoughts

Hooks made React fun again. No more fighting with this, long lifecycle methods, or confusing state logic.

For those new to hooks, it is recommended to start by gradually converting class components to functional components using hooks. As familiarity with hooks increases, many developers find them to be a more efficient and maintainable approach to building React applications.

October 20, 2022

Create Dynamic Timeline Component in React JS/TS.


SCENARIO

While working on one of the requirements for an Automobile sector project for a client based out of Dallas, Texas, There was a requirement to display dynamic timeline component with Expand/Collapse feature using React JS/TS.


CHALLENGE


There is no OOTB module OR component which we can utilize in React to meet this requirement. The only option is to develop custom component using JS/TS. 

APPROACH

We are going to create a custom and complete dynamic timeline component with additional feature like expand and collapse in React JS/TS.

Please follow the below details steps to meet requirement.

Step 1: 

Create React JS or React TS application. We can use following commands respectively for React JS and React TS.

    npx create-react-app timeline --template typescript

    npx create-react-app timeline

Step 2:

Once you execute the above command in your terminal you will get the following structure of your React Project.

Step 3 :

After Creating the project we need to add some plugin which you can install by executing the following commands.

    npm i @fortawesome/react-fontawesome

    npm i @fortawesome/free-solid-svg-icons

Step 4:

Now, Clear the project structure and we have to add new two files named as : Timeline.tsx and App.tsx.


Step 5:

Add the following Code to the Timeline.tsx file

In the above code we have defined function interface and the state as follows:

Interface Props : In React JS we get the Props directly from the parent component but in React TS we have to pass interface and from interface we get the props functions and variables. 

here we have one object for the timeline details and one function for the callback to set the state of Parent component.

updateStatus Function : This function will take the updated status as the argument and the object of timeline. So, this function will take both as a argument and update the status of current state and call the callback function from Props to and pass updated Timeline information object.

In render method we have taken a const variable timelineData which takes values from Props and then we have a return function which returns the timeline View based on different condition. Also, We have one flag named as "isOpen" which basically show the view between expand or collapse.

Step 6 : 

Once we are done with the timeline component, we will move to main App.tsx component. 

Add the following code to the App.tsx file. We can directly move this code into Index.tsx , but we want to create a dynamic component so we are adding a new component names as App.tsx 

In this file we have defined one static state object named as "timelineDetails". It contains the information of the timeline which we want to show on the component view as well as set flag to show status and expand collapse position. 

We also have one function names as "updateRecord", It accepts data as an argument which is an object of the timelineDetails. this function is going to be called from the Timeline.tsx file means the child component. This function finds the matching object from the timelineDetails and store in "tempTimeline" and then will replace the states object with the updated one.

Step 7 : 

Now add the following css to the App.css file for the designing and the expand/collapse view.

Step 8 :

At last, now execute the code and you will get below output with look & feel.


Expand View:


Collapse View : 


Conclusion : 

This component will create the dynamic view along with look & feel as per requirement. We can use this Timeline.tsx in any component outside of this project but we have to take care about the function and its parameter. 

We can use this timeline component as independent component with the expand and collapse functionality with complete dynamic Content.

August 29, 2019

Resolution: Open term is not allowed in PnP Taxonomy Picker control

Requirement:
We need to create a custom modern form which includes taxonomy picker control allowing Open Term. User should be allowed to add fill-in values - inserting new term on the fly.

Approach:
To meet above requirements, i've used PnP Taxonomy Picker control for SPFx.
https://sharepoint.github.io/sp-dev-fx-controls-react/controls/TaxonomyPicker/

Steps to add in Solution:
Import modules as below:

  • import { TaxonomyPicker, IPickerTerms } from "@pnp/spfx-controls-react/lib/TaxonomyPicker";

Use taxonomy picker control as below:
<TaxonomyPicker allowMultipleSelections={true}
                termsetNameOrID="Countries"
                panelTitle="Select Term"
                label="Taxonomy Picker"
                context={this.props.context}
                onChange={this.onTaxPickerChange}
                isTermSetSelectable={false} />

Limitation:
A limitation with this control is, it does not allow to fill-in values.

Resolution:
Finally, i've utilized another control that allows to add a new term is delaware Digital Workplace React Fabric Taxonomy picker.
https://www.npmjs.com/package/@dlw-digitalworkplace/react-fabric-taxonomypicker

Use below command to install npm package in your solution.

  • npm i @dlw-digitalworkplace/react-fabric-taxonomypicker

Import module as below:

  • import { TaxonomyPicker } from "@dlw-digitalworkplace/react-fabric-taxonomypicker";

Use taxonomy picker control as below:

<TaxonomyPicker
  title="Select your demo data"
  absoluteSiteUrl={this.props.absoluteSiteUrl}
  label="Demo picker"
  termSetId={this.props.termSetId}
  rootTermId={this.props.rootTermId}
  itemLimit={this.props.itemLimit}
  allowAddTerms={true}
  lcid={this.props.lcid}
  showTranslatedLabels={this.props.showTranslatedLabels}
  isLoading={false}
/>

Now, when user types in new term and press enter key, it will automatically create a new term in your selected term set id.

If you have any questions you can reach out our SharePoint Consulting team here.