Pick your app

The examples below will be updated with your app ID.

Platform features

Strong Init (experimental)

What if you could use the types you defined in instant.schema.ts, inside init? We have a new version of init out that lets you do this. It's in beta, but if you use it, useQuery and transact will automatically get typesafety and intellisense.

Here's how it works:

If you want to migrate, swap out init with init_experimental and pass it your app's schema object.

import { init_experimental } from '@instantdb/react';
// 1. Import your schema file
// Don't have a schema? check out https://www.instantdb.com/docs/cli to get started
import schema from '../instant.schema.ts';

const db = init_experimental({
  appId: '__APP_ID__',
  // 2. Use it inside `init_experimental`
  schema,
});

export default function App() {
  // 3. now useQuery is strongly typed!
  const todosRes = db.useQuery({
    todos: {},
  });

  function addTodo({ title: string }) {
    db.transact([
      // 4. mutations are typechecked too!
      db.tx.todos[id()].update({ title }),
    ]);
  }

  return <TodoApp todosRes={todosRes} onAddTodo={addTodo} />;
}

Changes to tx

If you used Instant before, you would use the global tx object. Instead, use the schema-aware db.tx.

// ✅ use `db.tx`
db.tx.todos[id()].update({ done: true }); // note the `db`

Changes to useQuery

Once you switch to init_experimental, your query results get more powerful too.

Previously, all responses in a useQuery returned arrays. Now, we can use your schema to decide. If you have a 'has one' relationship, we can return just one item directly.

Since the new useQuery is schema-aware, we know when to return a single item instead of an array. 🎉 Bear in mind that if you're migrating from init, you'll need to update all of your call sites that reference these "has-one" relationships.

const { data } = useQuery({ users: { author: {} } });
const firstUser = data.users[0];

// before
const author = firstUser.author[0];

// after
const author = firstUser.author; // no more array! 🎉

Reusable types

Sometimes, you'll want to abstract out your query and result types. For example, a query's result might be consumed across multiple React components, each with their own prop types. For such cases, we provide InstaQLParams and InstaQLResult.

To declare a query and validate its type against your schema, you can import InstantQuery and leverage TypeScript's satisfies operator like so:

const myQuery = { myTable: {} } satisfies InstaQLParams<typeof schema>;

To obtain the resolved result type of your query, import InstaQLResult and provide it your DB and query types:

type MyQueryResult = InstaQLResult<typeof schema, typeof myQuery>;

If you only want the type of a single entity, you can leverage InstaQLEntity. InstaQLEntity resolves an entity type from your DB:

type Todo = InstaQLEntity<typeof schema, 'todos'>;

You can specify links relative to the entity, too:

type TodoWithOwner = InstantEntity<
  typeof schema, 
  'todos', 
  { owner: {} }
>;

Here's a full example demonstrating reusable query types in a React app.