Jotai atoms for Loro Mirror: CRDT-backed atomic state with typed schema and bidirectional sync.
npm install loro-mirror-jotaiJotai integration for Loro Mirror, providing atomic state management with Loro
CRDT synchronization.
``bashUsing pnpm
pnpm add loro-mirror-jotai jotai loro-crdt
Usage
Create a
loroMirrorAtom to represent your shared state. It syncs automatically
with the provided Loro document.`tsx
import { useAtom } from 'jotai';
import { LoroDoc } from 'loro-crdt';
import { schema } from 'loro-mirror';
import { loroMirrorAtom } from 'loro-mirror-jotai';type TodoStatus = "todo" | "inProgress" | "done";
const todoSchema = schema.LoroMap(
{
text: schema.String(),
status: schema.String()
}
)
// Define your schema
const todoDocSchema = schema({
todos: schema.LoroList(
todoSchema,
(t) => t.$cid, // stable LoroMap id from Loro container id
)
});
// Auto generated type from schema
type Todo = InferType;
// Create a Loro document instance
const doc = new LoroDoc();
// Maybe subscribe the doc for persisting
let sub = doc.subscribe(......)
// Create the Jotai atom with Loro Mirror config
const todoDocAtom = loroMirrorAtom({
doc,
schema: todoDocSchema,
initialState: { todos: [] as Todo[] },
});
// Selector atom
const todosAtom = atom(get => get(todoDocAtom).todos, (_get, set, todos: Todo[]) => {
set(todoDocAtom, { todos })
})
// Action atom
const addTodoAtom = atom(null, (get, set, todo: Todo) => {
set(todosAtom, [...get(todosAtom), todo])
})
// Use it in your React component
function TodoApp() {
const todos = useAtomValue(todosAtom);
const addTodo = useSetAtom(addTodoAtom);
return (
{state.todos.map((todo) => (
- stable key from Loro container id /}>
{todo.text}: {todo.status}
))}
);
}
`$3
-
$cid is always present on LoroMap state and equals the underlying Loro
container id.
- Use $cid as a stable list selector and React key:
schema.LoroList(item, x => x.$cid) and