ReactJS Concurrent Rendering for Real-Time Data Visualization

2 min read

ReactJS Concurrent Rendering for Real-Time Data Visualization

Scenario

You’re managing:

  1. Real-time updates of incoming sales data from a WebSocket.
  2. User-applied filters to refine the displayed data.
  3. A dashboard with multiple data charts and tables that require re-rendering.

Concurrent rendering ensures that real-time data updates don’t block user interactions, while filter changes and graph re-rendering are deferred.

Step 1: Set Up the Component

import React, { useState, useEffect, useTransition } from "react";

function SalesDashboard() {
  const [salesData, setSalesData] = useState([]); // Full dataset
  const [filteredData, setFilteredData] = useState([]); // Displayed dataset
  const [isPending, startTransition] = useTransition(); // For deferred rendering
  const [filters, setFilters] = useState({ region: "", product: "" }); // Filters

  // Simulate real-time data updates using WebSocket
  useEffect(() => {
    const webSocket = new WebSocket("wss://example.com/sales-updates");
    webSocket.onmessage = (event) => {
      const newSales = JSON.parse(event.data);

      // Prioritize real-time updates immediately
      setSalesData((prevData) => [...prevData, ...newSales]);
    };

    return () => webSocket.close();
  }, []);

  // Handle user-applied filters with deferred updates
  const applyFilters = (newFilters) => {
    setFilters(newFilters);

    startTransition(() => {
      const updatedData = salesData.filter((sale) => {
        return (
          (!newFilters.region || sale.region === newFilters.region) &&
          (!newFilters.product || sale.product === newFilters.product)
        );
      });
      setFilteredData(updatedData); // Non-urgent rendering
    });
  };

  return (
    <div>
      <h1>Sales Dashboard</h1>

      {/* Filter Controls */}
      <FilterControls filters={filters} onApplyFilters={applyFilters} />

      {/* Loading Indicator */}
      {isPending && <p>Loading filtered data...</p>}

      {/* Data Visualization */}
      <DataCharts data={filteredData} />
      <DataTable data={filteredData} />
    </div>
  );
}

function FilterControls({ filters, onApplyFilters }) {
  const [region, setRegion] = useState(filters.region);
  const [product, setProduct] = useState(filters.product);

  const handleApply = () => {
    onApplyFilters({ region, product });
  };

  return (
    <div>
      <label>
        Region:
        <input value={region} onChange={(e) => setRegion(e.target.value)} />
      </label>
      <label>
        Product:
        <input value={product} onChange={(e) => setProduct(e.target.value)} />
      </label>
      <button onClick={handleApply}>Apply Filters</button>
    </div>
  );
}

function DataCharts({ data }) {
  // Render data into charts
  return <div>/* Visualization logic here */</div>;
}

function DataTable({ data }) {
  // Render data into a table
  return (
    <table>
      <thead>
        <tr>
          <th>Region</th>
          <th>Product</th>
          <th>Sales</th>
        </tr>
      </thead>
      <tbody>
        {data.map((row) => (
          <tr key={row.id}>
            <td>{row.region}</td>
            <td>{row.product}</td>
            <td>{row.sales}</td>
          </tr>
        ))}
      </tbody>
    </table>
  );
}

Breakdown of the Code

  1. Real-Time Updates:
    • The useEffect hook establishes a WebSocket connection to receive real-time sales data.
    • React prioritizes updating salesData immediately when new data arrives.
  2. Deferred Updates for Filters:
    • When a user applies filters, startTransition defers the computation and rendering of filteredData.
    • This ensures that the app remains responsive, even with large datasets.
  3. Visual Indicators:
    • The isPending flag from useTransition displays a loading message while React processes the filters.
  4. Multiple Components:
    • Filter controls allow users to modify criteria.
    • The data is visualized in charts and tables, re-rendering only when needed.

Benefits of Concurrent Rendering

  • Smooth User Experience: Real-time updates don’t interfere with filter selection or other interactions.
  • Optimized Performance: Filtering large datasets is handled efficiently without blocking the UI.
  • Scalable Architecture: The system can handle increasing complexity by delegating non-critical updates.

Conclusion

Concurrent Rendering transforms how React applications handle complex and dynamic interactions. By prioritizing critical tasks like real-time updates and deferring non-urgent rendering, it ensures a responsive and efficient UI. Whether you’re building dashboards, gaming apps, or data-driven interfaces, Concurrent Rendering helps create a seamless experience for users.

🤞 Never miss a story from us, get weekly updates to your inbox!