SurrealDB Docs Logo

Enter a search query

React

React

React is a popular JavaScript library for building user interfaces. The SurrealDB SDK for JavaScript can also be used in your React applications to interact with your SurrealDB instance.

In this guide, we will walk you through setting up and querying your first project with the SurrealDB SDK for React.

Prerequisites

This guide assumes the following:

  • You have a basic understanding of React.
  • You have installed SurrealDB on your machine

Setup

Install the SDK

First, install the SurrealDB SDK using your favorite package manager:

bun install surrealdb
Important

The SurrealDB SDK for JavaScript is also available in the JSR registry as @surrealdb/surrealdb.

Initialize the SDK

After installing the SDK, import it into your project. We recommend initializing the SDK in a Context Provider in order to expose it throughout your application. This makes the client accessible anywhere in your component tree, simplifies cleanup, and provides built-in state management for connection success or failure.

1. Install Required Packages

In addition to surrealdb, we recommend using @tanstack/react-query for managing the connection state:

bun install @tanstack/react-query

2. Creating the Context Provider

Create a new file, e.g., SurrealProvider.tsx, which will contain the context provider and hooks for accessing the SurrealDB client. You can copy the following code, which takes care of managing the connection.

Feel free to make any changes to fit your project structure and coding style.

src/contexts/SurrealProvider.tsx
import { Surreal } from "surrealdb"; import { useMutation } from "@tanstack/react-query"; import React, { createContext, useContext, useEffect, useMemo, useCallback, useState } from "react"; interface SurrealProviderProps { children: React.ReactNode; /** The database endpoint URL */ endpoint: string; /** Optional existing Surreal client */ client?: Surreal; /* Optional connection parameters */ params?: Parameters<Surreal["connect"]>[1]; /** Auto connect on component mount, defaults to true */ autoConnect?: boolean; } interface SurrealProviderState { /** The Surreal instance */ client: Surreal; /** Whether the connection is pending */ isConnecting: boolean; /** Whether the connection was successfully established */ isSuccess: boolean; /** Whether the connection rejected in an error */ isError: boolean; /** The connection error, if present */ error: unknown; /** Connect to the Surreal instance */ connect: () => Promise<true>; /** Close the Surreal instance */ close: () => Promise<true>; } const SurrealContext = createContext<SurrealProviderState | undefined>(undefined); export function SurrealProvider({ children, client, endpoint, params, autoConnect = true, }: SurrealProviderProps) { // Surreal instance remains stable across re-renders const [surrealInstance] = useState(() => client ?? new Surreal()); // React Query mutation for connecting to Surreal const { mutateAsync: connectMutation, isPending, isSuccess, isError, error, reset, } = useMutation({ mutationFn: () => surrealInstance.connect(endpoint, params), }); // Wrap mutateAsync in a stable callback const connect = useCallback(() => connectMutation(), [connectMutation]); // Wrap close() in a stable callback const close = useCallback(() => surrealInstance.close(), [surrealInstance]); // Auto-connect on mount (if enabled) and cleanup on unmount useEffect(() => { if (autoConnect) { connect(); } return () => { reset(); surrealInstance.close(); }; }, [autoConnect, connect, reset, surrealInstance]); // Memoize the context value const value: SurrealProviderState = useMemo( () => ({ client: surrealInstance, isConnecting: isPending, isSuccess, isError, error, connect, close, }), [surrealInstance, isPending, isSuccess, isError, error, connect, close], ); return <SurrealContext.Provider value={value}>{children}</SurrealContext.Provider>; } /** * Access the Surreal connection state from the context. */ export function useSurreal() { const context = useContext(SurrealContext); if (!context) { throw new Error("useSurreal must be used within a SurrealProvider"); } return context; } /** * Access the Surreal client from the context. */ export function useSurrealClient() { const { client } = useSurreal(); return client; }

3. Wrap Your Application with the Provider

In your top level component (usually index.tsx), wrap your root component with SurrealProvider:

src/index.tsx
import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; import { SurrealProvider } from "./SurrealProvider"; const root = ReactDOM.createRoot(document.getElementById("root")!); root.render( <React.StrictMode> <SurrealProvider endpoint="http://127.0.0.1:8000" autoConnect> <App /> </SurrealProvider> </React.StrictMode> );

4. Use the Hooks in Your Components

Anywhere inside the provider component tree, you can now access the Surreal client or check the connection status:

import { useEffect } from "react"; import { useSurreal, useSurrealClient } from "./SurrealProvider"; export function ExampleComponent() { const { client, isConnecting, isSuccess, isError, error, connect } = useSurreal(); // or if you only need the client: // const client = useSurrealClient(); useEffect(() => { if (isSuccess) { // Example: run a query once the connection is successful client.query("SELECT * FROM users").then(console.log).catch(console.error); } }, [isSuccess, client]); if (isConnecting) return <p>Connecting to SurrealDB...</p>; if (isError) return <p>Failed to connect: {String(error)}</p>; return ( <div> <h1>Users</h1> {/* Example button to manually reconnect */} <button onClick={connect}>Reconnect</button> </div> ); }

5. Customizing the Connection Logic

If you need custom logic (e.g., calling db.use(...), providing authentication tokens, etc.), you can:

  1. Use the params prop:

    <SurrealProvider endpoint="http://127.0.0.1:8000" params={{ namespace: "myNs", database: "myDb" }} > <App /> </SurrealProvider>
  2. Supply your own preconfigured Surreal instance:

    import Surreal from "surrealdb"; const customClient = new Surreal(); await customClient.connect("http://127.0.0.1:8000/rpc"); await customClient.use({ namespace: "myNs", database: "myDb" }); <SurrealProvider client={customClient} endpoint="http://127.0.0.1:8000" > <App /> </SurrealProvider>

Why Use a Provider?

  • Shared Connection: A single Surreal client instance is accessible to all your components.
  • Managed Lifecycle: Auto-connect on mount, reset on unmount, and handle errors gracefully.
  • Connection State: React Query simplifies loading, success, and error handling.

Using the SDK methods

If you are only interested in accessing SDK methods, you can use useSurrealClient() to directly obtain a reference to the Surreal client instance. In the example below, we use the .query() method which allows you write raw SurrealQL queries:

import { useState, useEffect } from "react"; import { useSurrealClient } from "./SurrealProvider"; export function ExampleComponent() { const client = useSurrealClient(); const [users, setUsers] = useState([]); const fetchUsers = async () => { try { const result = await client.query("SELECT * FROM users"); setUsers(result[0] || []); } catch (err) { console.error(err); } }; useEffect(() => { fetchUsers(); }, []); return ( <div> {users.map((user) => ( <div key={user?.id}> <h3>{user?.name}</h3> <p>Email: {user?.email}</p> </div> ))} {users.length === 0 && <p>No users found</p>} </div> ); }

Next steps

Now that you have SurrealDB integrated into your React project, you’re ready to start building! To learn more about interacting with your database:

© SurrealDB GitHub Discord Community Cloud Features Releases Install