Rows n’ Columns Docs
Visit HomepagePricing
  • Introduction
  • License
  • Demos
  • Getting started
    • Installation
    • Spreadsheet state
    • Headless UI
    • Imperative Spreadsheet API
    • Examples
  • ⚙️Configuration
    • Features
      • Data validation
      • Formula evaluation
      • Real-time data
      • Cell editors
      • Cell renderer
      • Structured Cell Renderer
      • Theming
      • Styling
      • Context menu
      • Localisation
      • Undo/Redo
      • Conditional formatting
      • Named ranges
      • Structured references
        • Schema based tables and columns
        • Calculated columns
      • Basic filter or Excel AutoFilter
      • Charts
      • Embedded content
      • Calculate on-demand
      • Drag and Drop
      • Pivoting and Grouping (Coming soon)
      • Tokenizer
      • Lazy loading/Infinite scrolling
      • OpenAI/Chat GPT Integration
      • Search
      • Formula protection
      • Autofill
      • Export canvas as image
    • Components
      • Canvas Grid
      • Toolbar
      • Sheet Tabs
      • Sheet Switcher
      • Sheet Status
      • Range Selector
      • Formula Input
      • Selection Input
      • SheetSearch
      • NamedRangeEditor
      • DeleteSheetConfirmation
      • TableEditor
      • Cell Format Editor
      • Conditional Format Editor
      • Data Validation Editor
      • Insert Link Editor
      • Insert Image Editor
    • API
      • Cell Data
      • Sheets
      • SpreadsheetProvider
      • useSpreadsheet
      • Modules
      • SheetCell
    • Using Spreadsheet with NextJS
    • Keyboard shortcuts
  • Collaboration
    • Real time collaboration
    • Yjs Collaboration
    • Supabase realtime Collaboration
  • Charts
    • Charts
    • Custom charts
  • Excel and Google sheets
    • CSV
    • Excel
    • Google sheets (Coming soon)
  • Functions
    • Named functions
    • Array formulas
  • Data persistence
    • Server side data persistence
    • React Query integration
  • Specifications
    • Browser support
    • Third party licenses
  • Support
    • Contact support
    • Report bugs
    • Feature requests
Powered by GitBook
On this page
  • Installation
  • Create a Query Provider

Was this helpful?

  1. Data persistence

React Query integration

React-query is a first-class library to manage asynchronous states

PreviousServer side data persistenceNextBrowser support

Last updated 1 year ago

Was this helpful?

For a working example of react-query integration, please take a look here

For this example, lets try to sync `sheets` state with a back-end server using react query

Installation

This document is based on React Query v3 -

yarn add @tanstack/react-query
npm i @tanstack/react-query

Create a Query Provider

Create a client and wrap the Spreadsheet with the provider

import { QueryClient, QueryClientProvider, useQueryClient  } from "@tanstack/react-query"
import { Sheet, CanvasGrid } from "@rowsncolumns/spreadsheet"
import { Skeleton } from "@rowsncolumns/ui"
import { useSpreadsheetState } from "@rowsncolumns/spreadsheet-state"

const client = new QueryClient();
const initialSheets: Sheet[] = [{ title: "Sheet1", id: 1]

const Spreadsheet = () => {
  const queryClient = useQueryClient();
  // Initial sheets data
  const { data: sheets = [], isLoading } = useQuery<Sheet[]>(
    "sheets",
    () => fetch(`/api/sheets`).then((res) => res.json()),
    {
      initialData: initialSheets,
    }
  );
  
  // Mutating sheets
  const { mutate } = useMutation(
    (newSheets: Sheet[]) => {
      return fetch(`/api/sheets/`, {
        method: "POST",
        body: JSON.stringify(newSheets),
        headers: { "Content-Type": "application/json" },
      });
    },
    {
      async onMutate(newSheets) {
        await queryClient.cancelQueries({ queryKey: ["sheets"] });

        const previousSheets = queryClient.getQueryData(["sheets"]);

        // Optimistically update to the new value
        queryClient.setQueryData(["sheets"], newSheets);

        return {
          previousSheets,
        };
      },
      onError(err, _, context) {
        queryClient.setQueryData(["sheets"], context?.previousSheets);
      },
      // Always refetch after error or success:
      onSettled: () => {
        queryClient.invalidateQueries({ queryKey: ["sheets"] });
      },
    }
  );

  // Update sheets
  const onChangeSheets = useCallback<UseSpreadsheetProps["onChangeSheets"]>(
    (mayBeCallbackOrValue) => {
      const previousSheets =
        queryClient.getQueryData<Sheet[]>(["sheets"]) ?? [];

      mutate(
        typeof mayBeCallbackOrValue === "function"
          ? mayBeCallbackOrValue(previousSheets)
          : mayBeCallbackOrValue
      );
    },
    [mutate]
  );
  
  
  // Use Spreadsheet hook
  const { } = useSpreadsheetState({
    sheets,
    onChangeSheets
  })
  
  if (isLoading) {
    return (
      <div className="flex border-solid border-rnc-border border border-t border-b flex-1 justify-center items-center">
        <div className="space-y-2">
          <Skeleton className="h-4 w-[250px]" />
          <Skeleton className="h-4 w-[250px]" />
        </div>
      </div>
    )
  }
  
  return (
    <CanvasGrid
    />
  )
  
}

export const App = () => (
  <QueryClientProvider client={client}>
    <SpreadsheetProvider>
      <Spreadsheet />
    </SpreadsheetProvider>
  </QueryClientProvider>
)

This logic can be isolated to its own to synchronize sheets between client and server.

The same logic can be applied to sheetData

https://github.com/rowsncolumns/spreadsheet/blob/main/examples/vite/spreadsheet-with-react-query.tsx
https://tanstack.com/query/v3/docs/react/installation