---
title: "Save and Load Reports Efficiently in React Pivot Table Using Redux"
published_at: "2025-02-11T10:42:37+00:00"
modified_at: "2025-02-11T11:53:36+00:00"
url: "https://www.syncfusion.com/blogs/post/save-load-report-in-react-pivot-table"
excerpt: "This blog explains how to efficiently save and load reports in the React Pivot Table using Redux with code examples."
taxonomy_category:
  - "Development"
  - "Pivot Table"
  - "React"
  - "UI"
  - "Web"
taxonomy_post_tag:
  - "development"
  - "Pivot Table"
  - "React"
  - "Redux"
  - "Reports"
  - "State management"
  - "Web"
---

# Save and Load Reports Efficiently in React Pivot Table Using Redux

[Sastha Prathap](https://www.syncfusion.com/blogs/author/sastha-prathap-selvamoorthy)

![Save and Load Reports Efficiently in React Pivot Table Using Redux](https://www.syncfusion.com/blogs/wp-content/uploads/2025/02/Save-and-Load-Reports-Efficiently-in-React-Pivot-Table-Using-Redux.png)


**TL;DR:** The React Pivot Table is a high-performance component for advanced data analysis, enabling robust data interaction. Integrating Redux with React Pivot Table simplifies state handling, making it easy to save, load, and manage reports within your app.

Syncfusion [React Pivot Table](https://www.syncfusion.com/react-components/react-pivot-table)
 is an advanced component for dynamic data analysis and reporting, giving users significant tools for analyzing and engaging with intricate data sets. As applications evolve and the requirement to manage several reports grows, operations such as saving, renaming, removing, fetching, and loading reports can get more complicated.

Here is where Redux comes into play! [Redux](https://redux.js.org/)
 is a state management library that provides a consistent and centralized approach for managing app states. Integrating Redux with [React Pivot Table](https://ej2.syncfusion.com/react/documentation/pivotview/getting-started)
 simplifies and streamlines report operations. Redux’s organized state management ensures that report data is handled consistently, making app maintenance, debugging, and scaling easier.

In this blog, we’ll see how to integrate Redux with React Pivot Table to efficiently handle report-related operations.

## Why use Redux?

Redux is ideal for apps requiring robust, scalable state management. Here’s why it may be perfect for your project:

- **Centralized state management:** Redux consolidates the entire app’s state into a single store, simplifying data management and updates.
- **** Predictable state updates:**** With a unidirectional data flow, Redux ensures consistent and traceable state changes, making debugging easier.
- **Enhanced debugging:** Redux DevTools provide detailed insights into each action and state change, helping developers diagnose and resolve issues more effectively.
- **** Separation of concerns:**** Redux separates state management from UI logic, leading to cleaner and more modular code.
- **Scalability:** Designed to manage complex states, Redux scales effectively with growing app requirements, making it suitable for apps that handle increasing complexity.
- **Consistent state across components:** By maintaining a single source of truth, Redux ensures that all components stay synchronized with the latest state, eliminating inconsistencies.
- **Improved testability:** Redux’s reliance on pure functions makes unit testing straightforward and dependable, enhancing code reliability and simplifying the testing process.

## Prerequisites

Before you begin, make sure you have the following:

1. **Basic knowledge of React:** Familiarity with [React](https://react.dev/learn) and its [component](https://react.dev/learn/your-first-component) -based architecture.
2. **Redux** b** asics:** A basic knowledge of [Redux](https://redux.js.org/introduction/getting-started) for state management, including actions, reducers, and the store.
3. **Node.js** and**npm:** Ensure [Node.js](https://nodejs.org/en) and [npm](https://nodejs.org/en/learn/getting-started/an-introduction-to-the-npm-package-manager) are installed to manage dependencies and run the development server.

## Setting up the project

To start, set up a new React project if you don’t already have one:

```
npx create-react-app pivot-table-redux-example
cd pivot-table-redux-example
```

### Install the required packages

Install the [React Pivot Table](https://helpej2.syncfusion.com/react/documentation/pivotview/getting-started)
 component along with the [Redux](https://redux.js.org/introduction/getting-started)
-related packages.

```
npm install @syncfusion/ej2-react-pivotview redux react-redux @reduxjs/toolkit
```

### Configuring Redux for state management

#### Step 1: Create a Redux slice

In the **reportSlice.js** file, define the state and reducers to manage reports. Refer to the following code example.

```
import { createSlice } from '@reduxjs/toolkit';
import { dataSource } from './data';

let defaultReport = {
  reportName: 'Sample Report', report: JSON.stringify({
    dataSourceSettings: {
      columns: [{ name: 'Year', caption: 'Production Year' }, { name: 'Quarter' }],
      dataSource: dataSource,
      expandAll: false,
      filters: [],
      formatSettings: [{ name: 'Amount', format: 'C0' }],
      rows: [{ name: 'Country' }, { name: 'Products' }],
      values: [{ name: 'Sold', caption: 'Units Sold' }, { name: 'Amount', caption: 'Sold Amount' }]
    }
  })
};

const reportSlice = createSlice({
  name: 'reports',
  initialState: {
    reports: [{
      reportName: 'Sample Report',
      report: defaultReport
    }],
    reportList: ['Sample Report'],
    currentReport: defaultReport,
    isInitial: true
  },
  reducers: {
    saveReport(state, action) {
      let isSave = state.reports.filter(report => report.reportName === action.payload.reportName).length > 0;
      if (!isSave) {
        state.reports.push(action.payload);
        state.reportList = state.reports.map(report => report.reportName);
      } else {
        state.reports = state.reports.map(report =>
          report.reportName === action.payload.reportName ? action.payload : report
        );
        state.isInitial = false;
      }
      state.currentReport = action.payload;
    },
    removeReport(state, action) {
      state.reports = state.reports.filter(report => report.reportName !== action.payload);
      state.reportList = state.reports.map(report => report.reportName);
      state.currentReport = state.reports[state.reports.length - 1];
    },
    renameReport(state, action) {
      state.reports = state.reports.map(report =>
        report.reportName === action.payload.reportName ? { ...report, reportName: action.payload.rename } : report
      );
      state.reportList = state.reports.map(report => report.reportName);
    },
    fetchReports(state) {
      state.reportList = state.reports.map(report => report.reportName);
    },
    loadReport(state, action) {
      state.currentReport = state.reports.filter(report => report.reportName === action.payload)[0];
    },
  },
});

export const {
  saveReport,
  saveAsReport,
  removeReport,
  renameReport,
  fetchReports,
  loadReport,
} = reportSlice.actions;

export default reportSlice.reducer;
```

In the above code example, we’ve defined the slice using **currentReport**, ** reportList**, and ** reports** based on the default report. Then, we created reducer actions for each report manipulation operation (Save, save as, rename, remove, fetch, and load) to update the reports in the Redux state.

- **Actions:** These are plain JavaScript objects that describe app events or changes. For example, ** saveReport** and ** loadReport** represent actions for the pivot table report.
- **Reducers:** These are functions that handle state changes in response to actions. They specify how the state should be updated based on the action received. The [createSlice](https://redux-toolkit.js.org/api/createSlice) function simplifies this by combining actions and reducers.

#### Step 2: Set up the Redux store

Now, create a file named **store.js** to configure your Redux store.

```
import { configureStore } from '@reduxjs/toolkit';
import reportReducer from './reportSlice'; // Ensure this is the correct path to your reducer

const store = configureStore({
    reducer: {
        reports: reportReducer,
    },
});

export default store;
```

**Store:** The Redux store is the central repository of the app state. In our example, the store is where we keep our pivot table reports.

#### Step 3: Configure the Provider

Wrap your app with Redux Provider in the **index.js** file.

```
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './store';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);
```

**Provider:** It is a component that makes the Redux store available to the rest of your app. It is used to wrap the root component so that all components have access to the store.

## Integrate the React Pivot Table in your app

The React Pivot Table has a user-friendly toolbar that includes predefined options for report manipulation. These options enable you to dynamically perform operations such as **save, save as, rename, load, delete,** and**add reports**. This [documentation](https://ej2.syncfusion.com/react/documentation/pivotview/tool-bar)
 will guide you through the process of integrating these predefined report manipulation options into the toolbar UI.


Built-in toolbar in React Pivot Table

Refer to the following code example to implement the code logic for the toolbar UI actions.

**[App.js]**

```
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { PivotViewComponent, Inject, FieldList, CalculatedField, Toolbar, PDFExport, ExcelExport, ConditionalFormatting, NumberFormatting } from '@syncfusion/ej2-react-pivotview';
import { saveReport, removeReport, renameReport, loadReport, fetchReports } from './reportSlice';
import './App.css';

function App() {
  const dispatch = useDispatch();
  const currentReport = useSelector(state => state.reports.currentReport);
  const reportList = useSelector(state => state.reports.reportList);
  const isInitial = useSelector(state => state.reports.isInitial);
  const dataSourceSettings = JSON.parse(currentReport.report).dataSourceSettings;

  useEffect(() => {
    updateReportList(reportList, currentReport.reportName);
  });

  let pivotObj;
  let toolbarOptions = ['New', 'Save', 'SaveAs', 'Rename', 'Remove', 'Load',
    'Grid', 'Chart', 'Export', 'SubTotal', 'GrandTotal', 'Formatting', 'FieldList'];
  function savePivotReport(args) {
    if (!isInitial) {
      dispatch(saveReport(args));
    }
  }
  function fetchReport() {
    dispatch(fetchReports());
  }
  function updateReportList(list, reportName) {
    if (pivotObj) {
      const reportListObj = (
        document.querySelector(
          '#' + pivotObj.element.id + '_reportlist'
        )
      ).ej2_instances;
      if (reportListObj) {
        reportListObj[0].dataSource = list;
        reportListObj[0].value = reportName;
        reportListObj[0].refresh();
      }
    }
  }
  function loadPivotReport(args) {
    dispatch(loadReport(args.reportName));
  }
  function removePivotReport(args) {
    dispatch(removeReport(args.reportName));
  }
  function renamePivotReport(args) {
    dispatch(renameReport(args));
  }
  function newReport() {
    pivotObj.setProperties({ dataSourceSettings: { columns: [], rows: [], values: [], filters: [] } }, false);
  }
  function dataBound() {
    if (pivotObj) {
      if (isInitial) {
        dispatch(saveReport({ reportName: 'Sample Report', report: pivotObj.getPersistData() }));
      }
      pivotObj.isModified = false;
    }
  }
  return (<PivotViewComponent id='PivotView' ref={d => pivotObj = d} dataSourceSettings={dataSourceSettings} width={'100%'} height={350} showFieldList={true} allowExcelExport={true} allowConditionalFormatting={true} allowNumberFormatting={true} allowPdfExport={true} showToolbar={true} allowCalculatedField={true} displayOption={{ view: 'Both' }} gridSettings={{ columnWidth: 120 }} toolbar={toolbarOptions} dataBound={dataBound.bind(this)} newReport={newReport.bind(this)} renameReport={renamePivotReport.bind(this)} removeReport={removePivotReport.bind(this)} loadReport={loadPivotReport.bind(this)} fetchReport={fetchReport.bind(this)} saveReport={savePivotReport.bind(this)}><Inject services={[FieldList, CalculatedField, Toolbar, PDFExport, ExcelExport, ConditionalFormatting, NumberFormatting]} /></PivotViewComponent>);
};

export default App;
```

**Dispatch:** It is the process of sending actions to the Redux store. When we save or load a report, we [dispatch](https://react-redux.js.org/api/hooks#usedispatch)
 the actions to update the state.

**Selectors:** They are functions that retrieve specific pieces of state from the Redux store. For instance, the [useSelector](https://react-redux.js.org/api/hooks#useselector)
 can obtain the current report or the list of saved reports.

Refer to the following code examples.

**[reportSlice.js]**

```
import { createSlice } from '@reduxjs/toolkit';
import { dataSource } from './data';

let defaultReport = {
  reportName: 'Sample Report', report: JSON.stringify({
    dataSourceSettings: {
      columns: [{ name: 'Year', caption: 'Production Year' }, { name: 'Quarter' }],
      dataSource: dataSource,
      expandAll: false,
      filters: [],
      formatSettings: [{ name: 'Amount', format: 'C0' }],
      rows: [{ name: 'Country' }, { name: 'Products' }],
      values: [{ name: 'Sold', caption: 'Units Sold' }, { name: 'Amount', caption: 'Sold Amount' }]
    }
  })
};

const reportSlice = createSlice({
  name: 'reports',
  initialState: {
    reports: [{
      reportName: 'Sample Report',
      report: defaultReport
    }],
    reportList: ['Sample Report'],
    currentReport: defaultReport,
    isInitial: true
  },
  reducers: {
    saveReport(state, action) {
      let isSave = state.reports.filter(report => report.reportName === action.payload.reportName).length > 0;
      if (!isSave) {
        state.reports.push(action.payload);
        state.reportList = state.reports.map(report => report.reportName);
      } else {
        state.reports = state.reports.map(report =>
          report.reportName === action.payload.reportName ? action.payload : report
        );
        state.isInitial = false;
      }
      state.currentReport = action.payload;
    },
    removeReport(state, action) {
      state.reports = state.reports.filter(report => report.reportName !== action.payload);
      state.reportList = state.reports.map(report => report.reportName);
      state.currentReport = state.reports[state.reports.length - 1];
    },
    renameReport(state, action) {
      state.reports = state.reports.map(report =>
        report.reportName === action.payload.reportName ? { ...report, reportName: action.payload.rename } : report
      );
      state.reportList = state.reports.map(report => report.reportName);
    },
    fetchReports(state) {
      state.reportList = state.reports.map(report => report.reportName);
    },
    loadReport(state, action) {
      state.currentReport = state.reports.filter(report => report.reportName === action.payload)[0];
    },
  },
});

export const {
  saveReport,
  saveAsReport,
  removeReport,
  renameReport,
  fetchReports,
  loadReport,
} = reportSlice.actions;

export default reportSlice.reducer;
```

**[store.js]**

```
import { configureStore } from '@reduxjs/toolkit';
import reportReducer from './reportSlice'; // Ensure this is the correct path to your reducer

const store = configureStore({
    reducer: {
        reports: reportReducer,
    },
});

export default store;
```

**[index.js]**

```
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { Provider } from 'react-redux';
import store from './store';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <Provider store={store}>
    <App />
  </Provider>
);
```

Let’s take a look at how to use the built-in toolbar options to save, load, and perform other report-related operations in the React Pivot Table using Redux one by one.

## Saving a report

When the **Save** option in the toolbar is clicked, the app prompts the user to enter the report name. Then, the [saveReport](https://ej2.syncfusion.com/react/documentation/pivotview/tool-bar#savereport)
 event is triggered. The name of the current report and its Pivot Table settings are saved in the Redux store via the Redux action **saveReport** (defined in the ** reportSlice.js** file).

For example, the report shown below will be passed to the **saveReport** action (defined in the ** reportSlice.js** file) with the name ** Sample Report** (the name ** Sample Report** comes from the source code by default, but you can change it in the code), and saved in the Redux store.


Saving a report in React Pivot Table using Redux

If you want to save a copy of the current report to the Redux store under a different name, select the **Save as current report** option from the toolbar UI.

When you click the **Save as current report** icon in the toolbar, the app prompts you to enter the new report name. The Pivot Table’s [saveReport](https://ej2.syncfusion.com/react/documentation/pivotview/tool-bar#savereport)
 event is then triggered, including the current (**Sample Report)** and latest report names(**Sample Report 1)**. As mentioned, these details are saved to the Redux store and passed to the Redux action ** saveReport** (defined in the ** reportSlice.js** file).


Saving a copy of the report in React Pivot Table using Redux

**Note:** The code snippets for the **Save** and ** Save as** reports are the same as mentioned above.

## Loading a report

When you select an item from the dropdown menu in the toolbar, the [loadReport](https://ej2.syncfusion.com/react/documentation/pivotview/tool-bar#loadreport)
 event is triggered. In this event, the Redux action **loadReport** (defined in the ** reportSlice.js** file) is invoked, with the selected report’s name as the parameter. This action retrieves the selected report from the Redux store using the provided report name and loads it into the Pivot Table.

For example, suppose the report **Sample Report** is selected from the dropdown menu. In that case, the Redux action ** loadReport** (defined in the ** reportSlice.js** file) will search for it in the Redux store, retrieve it, and load it into the Pivot Table.


Loading a report in React Pivot Table using Redux

## Renaming a report

When you select the **Rename a Current Report** option from the toolbar, you are prompted to provide the new report name. Afterward, the [renameReport](https://ej2.syncfusion.com/react/documentation/pivotview/tool-bar#renamereport)
 event is triggered with the latest report name. In this event, the Redux action **renameReport** (defined in the ** reportSlice.js** file) is invoked, passing the current and new report names. The report is identified using its current name and then updated with the new name in the Redux store.

For example, suppose we rename the current report from **Sample Report 1** to ** Sample Report 2**. In that case, ** Sample Report 1** and ** Sample Report 2** will be sent to the ** renameReport** Redux action (defined in the ** reportSlice.js** file), which will rename the current report to ** Sample Report 2** in the Redux store.


Renaming a report in the React Pivot Table using Redux

## Deleting a report

When you select the **Delete a Current Report** option from the toolbar, the [removeReport](https://ej2.syncfusion.com/react/documentation/pivotview/tool-bar#removereport)
 event is triggered with the current report name. In this event, the Redux action **removeReport** (defined in the ** reportSlice.js** file) is invoked, using the current report name to locate and delete the appropriate report from the Redux store.

For example, if you delete the current report **Sample Report 2** from the Pivot Table, the report name ** Sample Report 2** is sent to the ** removeReport** Redux action (defined in the ** reportSlice.js** file). This action then locates and removes the report from the Redux store.


Deleting a report in React Pivot Table using Redux

**Note:**  
1. If the Pivot Table’s current report n is removed, it will automatically load the last report in the list. This can be customized in the reducer action.  
2. If only one report is in the Pivot Table’s report list and removed, it will show the removed report state until a new report is added.

## Adding a report

When you select the **Create a New Report** option from the toolbar, the [newReport](https://ej2.syncfusion.com/react/documentation/pivotview/tool-bar#newreport)
 event is triggered first, followed by the [saveReport](https://ej2.syncfusion.com/react/documentation/pivotview/tool-bar#savereport)
 event. The **saveReport** event then saves the new report to the Redux store using the same Redux action ** saveReport** (defined in the ** reportSlice.js** file).


Adding a new report in React Pivot Table using Redux

## GitHub reference

For more details, refer to the [saving and loading reports in the React Pivot Table using Redux GitHub demo](https://github.com/SyncfusionExamples/react-pivot-table-saving-and-loading-reports-using-redux)
.


## Conclusion

Thank you for reading! In this blog, we’ve seen how to save, load, and perform other report-related operations in the Syncfusion [React Pivot Table](https://www.syncfusion.com/react-components/react-pivot-table)
 using Redux. We hope it helps you create a more dynamic and efficient data management system in your React apps.

For existing customers, the newest version of Essential Studio® is available for download from the [License and Downloads](https://www.syncfusion.com/account/downloads)
 page. If you are not a Syncfusion customer, try our 30-day [free trial](https://www.syncfusion.com/downloads)
 to check out the available features.

If you have questions, contact us through our [support forum](https://www.syncfusion.com/forums)
, [support portal](https://support.syncfusion.com/)
, or [feedback portal](https://www.syncfusion.com/feedback/)
. We are always happy to assist you!

## Related Blogs



[React Image Editor: Load and Save Images from a Database Easily](https://www.syncfusion.com/blogs/post/load-save-image-in-react-image-editor)



[How to Build an Accordion Tree in Preact Using the React TreeView Component?](https://www.syncfusion.com/blogs/post/build-accordion-tree-in-preact-app)



[RxJS for React: Unlocking Reactive States](https://www.syncfusion.com/blogs/post/react-rxjs-reactive-programming)



[The Top 5 React Chart Libraries to Know in 2026 for Modern Dashboards](https://www.syncfusion.com/blogs/post/top-5-react-chart-libraries)
