How to Use the React Data Grid Component

When I build a sales activity dashboard, I usually need the newest records at the top. A sales manager does not want to scroll past Monday’s calls to find the deal Olivia Johnson updated two minutes ago.

That sounds simple until you call reverse() on a React state array and the grid starts behaving strangely. I have seen rows switch unexpectedly, buttons show stale results, and original API data lose its intended order.

This practical React tutorial shows how to build a simple React Data Grid component and reverse its rows without mutating state.

What Is a React Data Grid Component?

A React Data Grid component displays structured data in rows and columns. You will often use one in dashboards, admin portals, customer support tools, inventory screens, and API-driven client-side applications.

For this tutorial, we will build a sales activity grid. Each row represents an activity created by a sales representative.

A component is a reusable JavaScript function that returns user interface content. React uses JSX, which looks like HTML inside JavaScript, to describe what appears in the browser.

Our grid will include:

  • A table with sales activity data
  • A button to reverse the display order
  • A safe immutable update
  • Stable row keys for reliable rendering
  • A reusable row component that receives props

If you are setting up a new project, start with this guide on how to set up a ReactJS environment and create your first React app.

Why Reversing Arrays Matters in a React Data Grid Component

Many APIs return records in oldest-first order. That order may work for data storage, but it rarely works for people reviewing live activity.

For example, an API might return activity records like this:

[
{ id: 101, rep: "Olivia Johnson", action: "Called Apex Retail", time: "9:05 AM" },
{ id: 102, rep: "Ethan Miller", action: "Sent proposal to Northstar Co.", time: "9:20 AM" },
{ id: 103, rep: "Mia Davis", action: "Updated deal amount", time: "9:45 AM" }
]

A dashboard often needs the opposite display order:

Mia Davis — Updated deal amount — 9:45 AM
Ethan Miller — Sent proposal to Northstar Co. — 9:20 AM
Olivia Johnson — Called Apex Retail — 9:05 AM

The key issue is that the JavaScript reverse() method changes the existing array. This behavior is called array mutation.

React expects you to treat state as read-only. State is data that React remembers between renders. When state changes through its setter function, React renders the component again and updates the browser view.

That is why you should create a new array before you reverse it.

Build a Basic React Data Grid Component

Let’s start with a complete functional component. A functional component is a normal JavaScript function that returns JSX.

This example uses the useState hook. A hook is a React function that lets a functional component use React features such as state.

import { useState } from "react";

const initialActivities = [
{
id: 101,
rep: "Olivia Johnson",
action: "Called Apex Retail",
time: "9:05 AM"
},
{
id: 102,
rep: "Ethan Miller",
action: "Sent proposal to Northstar Co.",
time: "9:20 AM"
},
{
id: 103,
rep: "Mia Davis",
action: "Updated deal amount",
time: "9:45 AM"
}
];

function ActivityRow({ activity }) {
return (
<tr>
<td>{activity.rep}</td>
<td>{activity.action}</td>
<td>{activity.time}</td>
</tr>
);
}

export default function SalesActivityGrid() {
const [activities] = useState(initialActivities);

return (
<section>
<h2>Sales Activity Dashboard</h2>

<table>
<thead>
<tr>
<th>Sales Rep</th>
<th>Activity</th>
<th>Time</th>
</tr>
</thead>

<tbody>
{activities.map((activity) => (
<ActivityRow key={activity.id} activity={activity} />
))}
</tbody>
</table>
</section>
);
}

This code stores activity records in a state array and renders them with map(). The map() method creates one ActivityRow component for every record.

The activity value is a prop. Props are values that a parent component passes to a child component. Here, SalesActivityGrid passes each activity object to ActivityRow.

The key prop uses the permanent id value. React uses keys to match existing rows with updated rows during rendering. Learn more about React props before you split larger grids into reusable components.

Sample output:

Sales Activity Dashboard

Sales Rep Activity Time
Olivia Johnson Called Apex Retail 9:05 AM
Ethan Miller Sent proposal to Northstar Co. 9:20 AM
Mia Davis Updated deal amount 9:45 AM

I executed the above example code and added the screenshot below.

Use the React Data Grid Component

Reverse React Data Grid Rows Safely

Now let’s add a button that reverses the sales activity order.

An event handler is a function that runs after a user action, such as clicking a button. We will use one to create a copied and reversed state array.

import { useState } from "react";

const initialActivities = [
{
id: 101,
rep: "Olivia Johnson",
action: "Called Apex Retail",
time: "9:05 AM"
},
{
id: 102,
rep: "Ethan Miller",
action: "Sent proposal to Northstar Co.",
time: "9:20 AM"
},
{
id: 103,
rep: "Mia Davis",
action: "Updated deal amount",
time: "9:45 AM"
}
];

function ActivityRow({ activity }) {
return (
<tr>
<td>{activity.rep}</td>
<td>{activity.action}</td>
<td>{activity.time}</td>
</tr>
);
}

export default function SalesActivityGrid() {
const [activities, setActivities] = useState(initialActivities);

function handleReverseRows() {
const reversedActivities = [...activities].reverse();
setActivities(reversedActivities);
}

return (
<section>
<h2>Sales Activity Dashboard</h2>

<button onClick={handleReverseRows}>
Reverse Activity Order
</button>

<table>
<thead>
<tr>
<th>Sales Rep</th>
<th>Activity</th>
<th>Time</th>
</tr>
</thead>

<tbody>
{activities.map((activity) => (
<ActivityRow key={activity.id} activity={activity} />
))}
</tbody>
</table>
</section>
);
}

The spread syntax, [...], creates a shallow copy of the activities array. Then reverse() changes only that copied array.

This is an immutable update, which means you create new data instead of changing existing state. React receives a new array reference through setActivities, so it knows to render the updated row order.

The button uses onClick, which connects the click event to the handleReverseRows function. You can learn more about handling events in React when you add filters, pagination, and action buttons to your grid.

Sample output before clicking the button:

Sales Activity Dashboard

Sales Rep Activity Time
Olivia Johnson Called Apex Retail 9:05 AM
Ethan Miller Sent proposal to Northstar Co. 9:20 AM
Mia Davis Updated deal amount 9:45 AM

Sample output after clicking “Reverse Activity Order”:

Sales Activity Dashboard

Sales Rep Activity Time
Mia Davis Updated deal amount 9:45 AM
Ethan Miller Sent proposal to Northstar Co. 9:20 AM
Olivia Johnson Called Apex Retail 9:05 AM

I executed the above example code and added the screenshot below.

React Data Grid Component

Pro Tip: I have found that mutating a state array directly is one of the fastest ways to create confusing React UI bugs. Always copy a state array before using methods such as reverse()sort(), or splice().

Use toReversed() for a Cleaner React Data Grid Component

Modern JavaScript includes toReversed(). Unlike the JavaScript reverse() method, it creates and returns a new reversed array without changing the original.

This approach reads well in a React component because it makes the immutable array update obvious.

import { useState } from "react";

const initialActivities = [
{
id: 101,
rep: "Olivia Johnson",
action: "Called Apex Retail",
time: "9:05 AM"
},
{
id: 102,
rep: "Ethan Miller",
action: "Sent proposal to Northstar Co.",
time: "9:20 AM"
},
{
id: 103,
rep: "Mia Davis",
action: "Updated deal amount",
time: "9:45 AM"
}
];

export default function SalesActivityGrid() {
const [activities, setActivities] = useState(initialActivities);

function handleReverseRows() {
setActivities((currentActivities) => currentActivities.toReversed());
}

return (
<section>
<h2>Sales Activity Dashboard</h2>

<button onClick={handleReverseRows}>
Show Latest Activity First
</button>

<table>
<thead>
<tr>
<th>Sales Rep</th>
<th>Activity</th>
<th>Time</th>
</tr>
</thead>

<tbody>
{activities.map((activity) => (
<tr key={activity.id}>
<td>{activity.rep}</td>
<td>{activity.action}</td>
<td>{activity.time}</td>
</tr>
))}
</tbody>
</table>
</section>
);
}

This version uses the updater form of setActivities. React passes the latest state value into currentActivities, which helps when users trigger several updates close together.

toReversed() returns a new array, so it protects the existing React state array. Use it when your project’s browser support and build setup allow it.

Sample output after clicking “Show Latest Activity First”:

Sales Activity Dashboard

Sales Rep Activity Time
Mia Davis Updated deal amount 9:45 AM
Ethan Miller Sent proposal to Northstar Co. 9:20 AM
Olivia Johnson Called Apex Retail 9:05 AM

I executed the above example code and added the screenshot below.

How to Use the React Data Grid Component

Reverse Rows Without Changing State

Sometimes the source order matters. For example, your activity state might match the API response, while the grid needs to show the newest activity first.

In that case, derive the reversed rows during rendering instead of saving a second state array.

import { useState } from "react";

const initialActivities = [
{
id: 101,
rep: "Olivia Johnson",
action: "Called Apex Retail",
time: "9:05 AM"
},
{
id: 102,
rep: "Ethan Miller",
action: "Sent proposal to Northstar Co.",
time: "9:20 AM"
},
{
id: 103,
rep: "Mia Davis",
action: "Updated deal amount",
time: "9:45 AM"
}
];

export default function SalesActivityGrid() {
const [activities] = useState(initialActivities);
const newestFirstActivities = [...activities].reverse();

return (
<section>
<h2>Sales Activity Dashboard</h2>
<p>Latest activity appears first.</p>

<table>
<thead>
<tr>
<th>Sales Rep</th>
<th>Activity</th>
<th>Time</th>
</tr>
</thead>

<tbody>
{newestFirstActivities.map((activity) => (
<tr key={activity.id}>
<td>{activity.rep}</td>
<td>{activity.action}</td>
<td>{activity.time}</td>
</tr>
))}
</tbody>
</table>
</section>
);
}

This React Data Grid component keeps activities in its original order. It creates newestFirstActivities only for display.

This pattern works well for static lists, small dashboard tables, and local frontend applications. It also avoids storing duplicate state, which makes components easier to maintain.

For larger data sets, calculate derived values carefully. You may need memoization with useMemo, which stores a calculated result until its dependencies change. However, do not add useMemo for a tiny list unless you see a real rendering issue.

Sample output:

Sales Activity Dashboard
Latest activity appears first.

Sales Rep Activity Time
Mia Davis Updated deal amount 9:45 AM
Ethan Miller Sent proposal to Northstar Co. 9:20 AM
Olivia Johnson Called Apex Retail 9:05 AM

Reverse API Data Before Rendering

Most real dashboards receive data from an API. You may fetch sales activities, support tickets, orders, or audit logs, then display the most recent item first.

The safest approach is to preserve the original response and derive the reversed display list.

import { useEffect, useState } from "react";

export default function SalesActivityGrid() {
const [activities, setActivities] = useState([]);
const [loading, setLoading] = useState(true);

useEffect(() => {
async function loadActivities() {
const apiResponse = [
{
id: 101,
rep: "Olivia Johnson",
action: "Called Apex Retail",
time: "9:05 AM"
},
{
id: 102,
rep: "Ethan Miller",
action: "Sent proposal to Northstar Co.",
time: "9:20 AM"
},
{
id: 103,
rep: "Mia Davis",
action: "Updated deal amount",
time: "9:45 AM"
}
];

setActivities(apiResponse);
setLoading(false);
}

loadActivities();
}, []);

const newestFirstActivities = activities.toReversed
? activities.toReversed()
: [...activities].reverse();

if (loading) {
return <p>Loading sales activity...</p>;
}

return (
<section>
<h2>Sales Activity Dashboard</h2>

<table>
<thead>
<tr>
<th>Sales Rep</th>
<th>Activity</th>
<th>Time</th>
</tr>
</thead>

<tbody>
{newestFirstActivities.map((activity) => (
<tr key={activity.id}>
<td>{activity.rep}</td>
<td>{activity.action}</td>
<td>{activity.time}</td>
</tr>
))}
</tbody>
</table>
</section>
);
}

The useEffect hook runs code after React renders the component. Developers commonly use it to load API data, connect subscriptions, and synchronize data with browser features.

This example uses local data to keep the code runnable without an external service. In a production admin portal, replace apiResponse with data from your API request. The code checks for toReversed() first and falls back to copying the array before calling reverse().

If your API data does not appear in the grid, review this guide on fixing React API data that is not displaying in a component.

Sample output after loading:

Sales Activity Dashboard

Sales Rep Activity Time
Mia Davis Updated deal amount 9:45 AM
Ethan Miller Sent proposal to Northstar Co. 9:20 AM
Olivia Johnson Called Apex Retail 9:05 AM

Things to Keep in Mind

  • Avoid direct state mutation: Never run activities.reverse() directly when activities comes from React state.
  • Copy before reverse(): Use [...activities].reverse() when you need broad compatibility with the JavaScript reverse() method.
  • Prefer derived values: Keep the original API response in state when only the display order changes.
  • Use stable keys: Use a permanent ID such as activity.id, not the array index, when you render lists in React.
  • Avoid duplicate state: Do not store both original and reversed arrays unless users must edit each order independently.
  • Skip unnecessary updates: For static arrays, reverse a copied display array instead of calling a state setter after every render.

Frequently Asked Questions

How do I reverse an array in React without changing the original array?

Create a new array before calling reverse(). Use const reversedItems = [...items].reverse().
You can also use items.toReversed() in modern JavaScript environments. Both approaches leave the original array unchanged.

Why does reverse() cause problems with React state?

The reverse() method changes the same array object. If that array belongs to React state, you mutate state directly instead of creating a new value.
React applications work best when you use immutable array updates. Create a copy, reverse the copy, and pass that new array to the state setter.

Can I use toReversed() in a React application?

Yes. toReversed() creates a new reversed array and does not mutate the original state array.
Check that your target browsers and project setup support it. If you need broader compatibility, use [...items].reverse().

How do I reverse an array with useState?

Use the useState hook setter with a copied array. For example, call setItems((currentItems) => [...currentItems].reverse()).
The updater function receives the latest state value. This makes your event handler more reliable when React processes multiple updates.

Should I reverse API data before displaying it in React?

Usually, keep the original API response in state and reverse a copied array for display. This protects the response order for other calculations, filters, and exports.
Use stored reversed state only when the user needs to change and keep the current grid order.

How do I render a reversed array using map() in React?

Create the reversed array first, then call map() on it. For example, use const rows = [...activities].reverse(); and render rows.map(...).
Always use stable keys from your data, such as an ID. This helps React update table rows correctly.

A React Data Grid component becomes easier to maintain when you keep its state predictable. Create a copy before calling reverse(), or use toReversed() when your browser support and project setup allow it.

That small habit protects your API data, avoids state mutation bugs, and keeps your dashboard rows reliable. I hope you found this article helpful.

You May Also Like

Leave a Comment

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.