SurrealDB Docs Logo

Enter a search query

SolidJS

SolidJS

SolidJS is a modern JavaScript framework designed to build responsive and high-performing user interfaces (UI). It prioritizes a simple and predictable development experience, making it a great choice for developers of all skill levels.

The SurrealDB SDK for JavaScript can also be used in your SolidJS 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 SolidJS.

Prerequisites

This guide assumes the following:

  • You have a basic understanding of SolidJS.
  • 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/solid-query for managing manage the asynchronous connection state to the SurrealDB database.

Specifically, createMutation to create a managed mutation that handles the connection lifecycle. It provides built-in state management for the async operation, automatically tracking loading states (isError, error), and provides utilities like reset to handle errors and retry operations if needed.

You can install the package using your favorite package manager:

bun install @tanstack/solid-query

2. Creating the Context Provider

The best way to manage the connection state is to create a context provider that will handle the connection and provide the client to the rest of the application. In SolidJS, we can use the createContext function to create a context and the createStore function to manage the state.

First, 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.

Note

We do recommend adding this in a lib/providers directory, but you can place it wherever you see fit.

src/lib/providers/SurrealProvider.tsx
import { useContext, createContext, JSX, createSignal, createEffect, onCleanup, Accessor, onMount } from "solid-js"; import Surreal from "surrealdb"; import { createMutation } from "@tanstack/solid-query"; import { createStore } from "solid-js/store"; interface SurrealProviderProps { children: JSX.Element; /** 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: Accessor<Surreal>; /** Whether the connection is pending */ isConnecting: Accessor<boolean>; /** Whether the connection was successfully established */ isSuccess: Accessor<boolean>; /** Whether the connection rejected in an error */ isError: Accessor<boolean>; /** The connection error, if present */ error: Accessor<unknown|null>; /** Connect to the Surreal instance */ connect: () => Promise<void>; /** Close the Surreal instance */ close: () => Promise<true>; } // Store interface to track the Surreal instance and connection status interface SurrealProviderStore { instance: Surreal; status: "connecting" | "connected" | "disconnected"; } const SurrealContext = createContext<SurrealProviderState>(); export function SurrealProvider(props: SurrealProviderProps) { // Initialize store with either provided client or new instance const [store, setStore] = createStore<SurrealProviderStore>({ instance: props.client ?? new Surreal(), status: "disconnected" }); // Use TanStack Query's mutation hook to manage the async connection state const { mutateAsync, isError, error, reset } = createMutation(() => ({ mutationFn: async () => { setStore("status", "connecting"); await store.instance.connect(props.endpoint, props.params); } })); // Effect to handle auto-connection and cleanup createEffect(() => { // Connect automatically if autoConnect is true if(props.autoConnect) { mutateAsync(); } // Cleanup function to reset mutation state and close connection onCleanup(() => { reset(); store.instance.close(); }); }); // Subscribe to connection events when component mounts onMount(() => { // Update store status when connection is established store.instance.emitter.subscribe("connected", () => { setStore("status", "connected"); }); // Update store status when connection is lost store.instance.emitter.subscribe("disconnected", () => { setStore("status", "disconnected"); }); }); // Create the value object that will be provided through context const providerValue: SurrealProviderState = { client: () => store.instance, close: () => store.instance.close(), connect: mutateAsync, error: () => error, isConnecting: () => store.status === "connecting", isError: () => isError, isSuccess: () => store.status === "connected" }; return ( <SurrealContext.Provider value={providerValue}> {props.children} </SurrealContext.Provider> ); } // Custom hook to access the SurrealDB context export function useSurreal(): SurrealProviderState { const context = useContext(SurrealContext); // Ensure the hook is used within a provider if(!context) { throw new Error("useSurreal must be used within a SurrealProvider"); } return context; }

3. Wrap Your Application with the Provider

After creating the SurrealProvider, you’ll need to wrap your application’s root component with it. Here’s an example of how to set up your App.tsx component with the necessary providers. We’re using both the QueryClientProvider for managing async state and our custom SurrealProvider for database connectivity, along with routing and authentication setup:

src/App.tsx
import type { Component } from 'solid-js'; import { Router, Route } from "@solidjs/router"; import { SurrealProvider } from './lib/providers/SurrealProvider'; import { QueryClientProvider } from '@tanstack/solid-query'; import { tanstackClient } from './lib/query-client'; import { AuthProvider } from './lib/providers/auth'; import { AppLayout } from './components/layout/app'; const App: Component = () => { return ( <QueryClientProvider client={tanstackClient}> <SurrealProvider endpoint={import.meta.env.VITE_DB_HOST} autoConnect params={{ namespace: "surrealdb", database: "pollwebapp", }} > <AuthProvider> <Router> <Route path="/" component={AppLayout}> ... your routes here </Route> </Router> </AuthProvider> </SurrealProvider> </QueryClientProvider> ); }; export default App;

4. Use the useSurreal Hook in Your Components

Now you can use the useSurreal hook in your components to access the SurrealDB client. For example, you can create an AuthProvider to handle authentication and user management.

src/lib/providers/AuthProvider.tsx
import { Accessor, createContext, ParentProps, useContext } from "solid-js"; import { createStore } from "solid-js/store"; import { useSurreal } from "../lib/providers/SurrealProvider"; interface AuthProviderState { user: Accessor<UserRecord | undefined>; login: (email: string, password: string) => Promise<void>; register: (data: Omit<UserRecord, "id">) => Promise<void>; logout: () => Promise<void>; } interface AuthProviderStore { user: UserRecord | undefined; status: "idle" | "signing-in" | "signing-up" | "signing-out" | "signed-in" | "signed-up"; } const AuthContext = createContext<AuthProviderState>(); export function AuthProvider(props: ParentProps) { const { client, close, connect } = useSurreal(); const [store, setStore] = createStore<AuthProviderStore>({ user: undefined, status: "idle" }); const login = async (email: string, password: string) => { const db = client(); setStore("status", "signing-in"); await db.signin({ access: "user", namespace: "surrealdb", database: "pollwebapp", variables: { email: email, pass: password } }); setStore("status", "signed-up"); }; const register = async (data: Omit<UserRecord, "id">) => { const db = client(); setStore("status", "signing-up"); await db.signup({ access: "user", namespace: "surrealdb", database: "pollwebapp", variables: data }); setStore("status", "signed-up"); }; const logout = async () => { setStore("status", "signing-out"); await close(); await connect(); setStore("status", "idle"); }; const providerValue: AuthProviderState = { user: () => store.user, login, register, logout }; return ( <AuthContext.Provider value={providerValue}> {props.children} </AuthContext.Provider> ); } export function useAuth(): AuthProviderState { const ctx = useContext(AuthContext); if(!ctx) { throw new Error("useAuth must be used within an AuthProvider"); } return ctx; }

Next steps

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

© SurrealDB GitHub Discord Community Cloud Features Releases Install