DEV Community

Nathan Collins
Nathan Collins

Posted on

Advanced Data Grid Implementation with DevExtreme React Grid

DevExtreme React Grid is a powerful, enterprise-grade data grid component for React that provides comprehensive functionality including sorting, filtering, grouping, editing, and virtualization. It's part of the DevExtreme suite, offering a plugin-based architecture that allows extensive customization and advanced features for building complex data management interfaces. This guide walks through implementing advanced grid features using DevExtreme React Grid with React, covering plugin configuration, custom editors, and enterprise-grade implementations. This is part 18 of a series on using DevExtreme React Grid with React.

Prerequisites

Before you begin, ensure you have:

  • Node.js version 16.0 or higher
  • npm, yarn, or pnpm package manager
  • A React project (version 16.8 or higher) with hooks support
  • Advanced understanding of React hooks, context API, and state management
  • Familiarity with TypeScript (highly recommended)
  • Knowledge of plugin architectures and component composition

Installation

Install DevExtreme React Grid and its dependencies:

npm install @devextreme/runtime @devextreme/react-grid devextreme
Enter fullscreen mode Exit fullscreen mode

Or with yarn:

yarn add @devextreme/runtime @devextreme/react-grid devextreme
Enter fullscreen mode Exit fullscreen mode

Or with pnpm:

pnpm add @devextreme/runtime @devextreme/react-grid devextreme
Enter fullscreen mode Exit fullscreen mode

Your package.json should include:

{
  "dependencies": {
    "@devextreme/react-grid": "^3.0.0",
    "@devextreme/runtime": "^3.0.0",
    "devextreme": "^23.0.0",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Project Setup

DevExtreme requires CSS styles to be imported. Add the styles to your main application file:

// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import 'devextreme/dist/css/dx.light.css';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

First Example / Basic Usage

Let's create a basic grid component. Create src/DataGrid.jsx:

// src/DataGrid.jsx
import React from 'react';
import {
  Grid,
  Table,
  TableHeaderRow,
} from '@devextreme/react-grid';

function DataGrid() {
  const columns = [
    { dataField: 'id', caption: 'ID', width: 80 },
    { dataField: 'name', caption: 'Name' },
    { dataField: 'email', caption: 'Email' },
    { dataField: 'age', caption: 'Age', width: 100 },
    { dataField: 'city', caption: 'City' }
  ];

  const data = [
    { id: 1, name: 'John Doe', email: 'john@example.com', age: 28, city: 'New York' },
    { id: 2, name: 'Jane Smith', email: 'jane@example.com', age: 32, city: 'London' },
    { id: 3, name: 'Bob Johnson', email: 'bob@example.com', age: 45, city: 'Paris' },
    { id: 4, name: 'Alice Williams', email: 'alice@example.com', age: 29, city: 'Tokyo' }
  ];

  return (
    <div style={{ padding: '20px' }}>
      <h2>Employee Directory</h2>
      <Grid
        dataSource={data}
        showBorders={true}
      >
        <Table />
        <TableHeaderRow />
      </Grid>
    </div>
  );
}

export default DataGrid;
Enter fullscreen mode Exit fullscreen mode

Understanding the Basics

DevExtreme React Grid uses a plugin-based architecture where:

  • Grid: Main component that wraps the grid
  • Plugins: Modular features (Table, TableHeaderRow, Sorting, Filtering, etc.)
  • Columns: Array of column definition objects
  • dataSource: Array of row data objects
  • dataField: Maps to a property in your row data

Key concepts for advanced usage:

  • Plugin System: Compose features by adding plugin components
  • Column Definitions: Define structure with dataField, caption, and options
  • State Management: Grid manages its own state or can be controlled
  • Customization: Extensive options for styling, behavior, and functionality

Here's an example with sorting and filtering:

// src/AdvancedGrid.jsx
import React from 'react';
import {
  Grid,
  Table,
  TableHeaderRow,
  TableFilterRow,
  SortingState,
  FilteringState,
  IntegratedSorting,
  IntegratedFiltering,
} from '@devextreme/react-grid';

function AdvancedGrid() {
  const [sorting, setSorting] = React.useState([]);
  const [filters, setFilters] = React.useState([]);

  const columns = [
    { dataField: 'id', caption: 'ID', width: 80 },
    { dataField: 'name', caption: 'Name' },
    { dataField: 'email', caption: 'Email' },
    { dataField: 'age', caption: 'Age', width: 100 },
    { dataField: 'city', caption: 'City' }
  ];

  const data = [
    { id: 1, name: 'John Doe', email: 'john@example.com', age: 28, city: 'New York' },
    { id: 2, name: 'Jane Smith', email: 'jane@example.com', age: 32, city: 'London' },
    { id: 3, name: 'Bob Johnson', email: 'bob@example.com', age: 45, city: 'Paris' }
  ];

  return (
    <Grid
      dataSource={data}
      columns={columns}
      showBorders={true}
    >
      <SortingState
        sorting={sorting}
        onSortingChange={setSorting}
      />
      <FilteringState
        filters={filters}
        onFiltersChange={setFilters}
      />
      <IntegratedSorting />
      <IntegratedFiltering />
      <Table />
      <TableHeaderRow allowSorting />
      <TableFilterRow />
    </Grid>
  );
}

export default AdvancedGrid;
Enter fullscreen mode Exit fullscreen mode

Practical Example / Building Something Real

Let's build a comprehensive employee management grid with editing, grouping, and advanced features:

// src/EmployeeManagement.jsx
import React, { useState } from 'react';
import {
  Grid,
  Table,
  TableHeaderRow,
  TableFilterRow,
  TableGroupRow,
  TableEditRow,
  TableEditColumn,
  TableSelection,
  GroupingState,
  SortingState,
  FilteringState,
  EditingState,
  SelectionState,
  IntegratedSorting,
  IntegratedFiltering,
  IntegratedGrouping,
  IntegratedSelection,
} from '@devextreme/react-grid';

function EmployeeManagement() {
  const [data, setData] = useState([
    { 
      id: 1, 
      name: 'Sarah Johnson', 
      email: 'sarah@example.com',
      department: 'Engineering', 
      salary: 95000, 
      startDate: '2020-01-15',
      status: 'Active'
    },
    { 
      id: 2, 
      name: 'Michael Chen', 
      email: 'michael@example.com',
      department: 'Marketing', 
      salary: 75000, 
      startDate: '2019-06-20',
      status: 'Active'
    },
    { 
      id: 3, 
      name: 'Emily Davis', 
      email: 'emily@example.com',
      department: 'Sales', 
      salary: 65000, 
      startDate: '2021-03-10',
      status: 'Active'
    },
    { 
      id: 4, 
      name: 'David Wilson', 
      email: 'david@example.com',
      department: 'Engineering', 
      salary: 110000, 
      startDate: '2018-09-05',
      status: 'Active'
    }
  ]);

  const [sorting, setSorting] = useState([]);
  const [filters, setFilters] = useState([]);
  const [grouping, setGrouping] = useState([{ columnName: 'department' }]);
  const [selection, setSelection] = useState([]);
  const [editingState, setEditingState] = useState({});

  const columns = [
    { 
      dataField: 'id', 
      caption: 'ID', 
      width: 80,
      allowEditing: false
    },
    { 
      dataField: 'name', 
      caption: 'Employee Name',
      cellRender: ({ value, row }) => (
        <div>
          <strong>{value}</strong>
          <div style={{ fontSize: '12px', color: '#666' }}>
            {row.data.email}
          </div>
        </div>
      )
    },
    { 
      dataField: 'department', 
      caption: 'Department',
      cellRender: ({ value }) => {
        const colors = {
          Engineering: '#dc3545',
          Marketing: '#ffc107',
          Sales: '#28a745',
          HR: '#17a2b8'
        };
        return (
          <span style={{
            padding: '4px 8px',
            borderRadius: '4px',
            backgroundColor: colors[value] || '#6c757d',
            color: 'white',
            fontSize: '12px'
          }}>
            {value}
          </span>
        );
      }
    },
    { 
      dataField: 'salary', 
      caption: 'Salary',
      dataType: 'number',
      format: { type: 'currency', currency: 'USD' },
      cellRender: ({ value }) => `$${value.toLocaleString()}`
    },
    { 
      dataField: 'startDate', 
      caption: 'Start Date',
      dataType: 'date',
      cellRender: ({ value }) => {
        const date = new Date(value);
        return date.toLocaleDateString('en-US');
      }
    },
    { 
      dataField: 'status', 
      caption: 'Status',
      cellRender: ({ value }) => (
        <span style={{
          padding: '4px 8px',
          borderRadius: '4px',
          backgroundColor: value === 'Active' ? '#d4edda' : '#f8d7da',
          color: value === 'Active' ? '#155724' : '#721c24',
          fontWeight: 'bold'
        }}>
          {value}
        </span>
      )
    }
  ];

  const commitChanges = ({ added, changed, deleted }) => {
    let changedData = [...data];

    if (added) {
      const startingAddedId = data.length > 0 ? data[data.length - 1].id + 1 : 0;
      changedData = [
        ...changedData,
        ...added.map((row, index) => ({
          id: startingAddedId + index,
          ...row
        }))
      ];
    }

    if (changed) {
      changedData = changedData.map(row => 
        changed[row.id] ? { ...row, ...changed[row.id] } : row
      );
    }

    if (deleted) {
      const deletedSet = new Set(deleted);
      changedData = changedData.filter(row => !deletedSet.has(row.id));
    }

    setData(changedData);
  };

  return (
    <div style={{ padding: '20px' }}>
      <h2>Employee Management</h2>
      <Grid
        dataSource={data}
        columns={columns}
        showBorders={true}
      >
        <SortingState
          sorting={sorting}
          onSortingChange={setSorting}
        />
        <FilteringState
          filters={filters}
          onFiltersChange={setFilters}
        />
        <GroupingState
          grouping={grouping}
          onGroupingChange={setGrouping}
        />
        <SelectionState
          selection={selection}
          onSelectionChange={setSelection}
        />
        <EditingState
          onCommitChanges={commitChanges}
        />
        <IntegratedSorting />
        <IntegratedFiltering />
        <IntegratedGrouping />
        <IntegratedSelection />
        <Table />
        <TableHeaderRow allowSorting allowGrouping />
        <TableFilterRow />
        <TableGroupRow />
        <TableSelection showSelectAll />
        <TableEditRow />
        <TableEditColumn
          showAddCommand
          showEditCommand
          showDeleteCommand
        />
      </Grid>
    </div>
  );
}

export default EmployeeManagement;
Enter fullscreen mode Exit fullscreen mode

This advanced example demonstrates:

  • Multiple plugins working together (sorting, filtering, grouping, selection, editing)
  • Custom cell rendering with React components
  • Row grouping by department
  • Row selection with select all
  • Inline editing with add, edit, delete commands
  • Custom formatting (currency, dates)
  • Conditional styling
  • State management for all features

Common Issues / Troubleshooting

  1. Grid not rendering: Ensure you've imported the CSS file (devextreme/dist/css/dx.light.css). Verify that all required plugins are imported and added to the Grid component.

  2. Plugins not working: Make sure you've added the plugin components as children of Grid and included the corresponding state management plugins (e.g., SortingState with IntegratedSorting).

  3. Editing not working: Include EditingState and TableEditRow/TableEditColumn plugins. Implement the onCommitChanges handler to update your data.

  4. Grouping not working: Add GroupingState and IntegratedGrouping plugins. Set initial grouping state with column names.

  5. TypeScript errors: DevExtreme has excellent TypeScript support. Ensure your column and data types match the expected interfaces.

Next Steps

Now that you've mastered DevExtreme React Grid:

  • Explore advanced features like virtual scrolling and column resizing
  • Implement custom editors and validators
  • Add server-side data loading and pagination
  • Learn about column pinning and reordering
  • Explore tree grid features for hierarchical data
  • Add export functionality (Excel, PDF)
  • Check the official documentation: https://devexpress.github.io/devextreme-reactive/react/grid/
  • Look for part 19 of this series for more advanced topics

Summary

You've learned how to implement advanced data grid features with DevExtreme React Grid, including sorting, filtering, grouping, editing, and selection using a plugin-based architecture. The library provides extensive functionality for building enterprise-grade data management interfaces with excellent performance and customization options.

SEO Keywords

DevExtreme React Grid
DevExtreme React Grid tutorial
React data grid DevExtreme
DevExtreme React Grid installation
React enterprise grid
DevExtreme React Grid example
React table component advanced
DevExtreme React Grid setup
React interactive grid
DevExtreme React Grid filtering
React data grid library
DevExtreme React Grid grouping
React table with editing
DevExtreme React Grid pagination
React enterprise data grid

Top comments (0)