Skip to main content

React integration

SyncedStore is designed to work seamlessly with React. Below, you'll find a basic todo app. You'll notice that the code is almost as simple as building a regular todo app.

Defining the store is done in store.ts. Then, we import this store with the useSyncedStore hook into our App component. Now, adding a todo item is as simple as calling state.todos.push({ completed: false, title: "Get groceries" });.

import React from "react";
import { useSyncedStore } from "@syncedstore/react";
import { store } from "./store";

export default function App() {
  const state = useSyncedStore(store);

  return (
      <p>Todo items:</p>
        {, i) => {
          return (
            <li key={i} style={{ textDecoration: todo.completed ? "line-through" : "" }}>
                <input type="checkbox" checked={todo.completed} onClick={() => (todo.completed = !todo.completed)} />
        placeholder="Enter a todo item and hit enter"
        onKeyPress={(event) => {
          if (event.key === "Enter") {
            const target = as HTMLInputElement;
            // Add a todo item using the text added in the textfield
            state.todos.push({ completed: false, title: target.value });
            target.value = "";
        style={{ width: "200px", maxWidth: "100%" }}

Mutable store

If you're an experienced React developer, and used to using the useState hook to manage state, you'll notice a slight difference in how SyncedStore stores work. Instead of immutable state, with SyncedStore and the useSyncedStore hook, you can mutate variables on the store directly.

SyncedStore uses the concept of Functional Reactive Programming, and in that way is similar to React state management libraries like MobX.

Fancy words, but this actually makes your life a lot easier.

useSyncedStore Hook

The useSyncedStore hook takes one parameter, which should be the store returned from the syncedStore method.

const state = useSyncedStore(store);

The useSyncedStore hook is pretty smart. It automatically detects which properties of state you use in your React component.

If you only read from state.todos[0].title, your component rerenders if and only if the title of the first "todo" changes, whether that's by you or by a remote user. So, when another property changes (e.g.: a different todo item), your component doesn't rerender. Preventing these unnecessary rerenders improves the performance of your app.

Learning more (advanced)

You can also pass a nested object (store.vehicles) or a Yjs object (e.g.: Y.Doc, Y.Array or Y.Map) to the useSyncedStore method (for example, if you're already using Yjs in your app and just want to utilize SyncedStore's more idiomatic API).

To learn more, the useSyncedStore is actually a wrapper for useReactive, from the reactive library.