Skip to main content
Version: Next

Conflict-Free Replicated Data Type

The syncCRDT function ensures automatic conflict resolution when syncing state across multiple users / devices.

It is ideal for collaborative apps, like:

  • ✅ Shared Todo Lists
  • ✅ Real-Time Note Taking
  • ✅ Multi-User Document Editing
  • ✅ Live Counters or Votes

✅ Example 1: CRDT-Based Shared Todo List

This syncs todos across multiple users and merges conflicting changes automatically.

🔹 Step 1: Setup WebSocket for Syncing (src/socket/websocket.ts):

src/socket/websocket.ts
import { todoState } from "../components/TodoApp"
const socket = new WebSocket("ws://localhost:4000");

socket.onmessage = (event) => {
const { key, data } = JSON.parse(event.data);
if (key === "todos") syncCRDT(data, todoState);
};

export const syncTodos = (state) => {
socket.send(JSON.stringify({ key: "todos", data: state }));
};

🔹 Step 2: Use CRDT in src/components/TodoApp.tsx:

src/components/TodoApp.tsx
import { useStateGlobal, syncCRDT } from "state-jet";
import { syncTodos } from "../socket/websocket";

export type Todo = { id: number; text: string; completed: boolean };

export const todoState = useStateGlobal<Todo[]>("todos", []);

export default function TodoApp() {
const todos = todoState.useState() as Todo[];

const addTodo = (text: string) => {
const newTodos = [...todos, { id: Date.now(), text, completed: false }];
syncCRDT(newTodos, todoState);
syncTodos(newTodos); // Send to WebSocket
};

return (
<div>
<h1>Shared Todo List</h1>
<button onClick={() => addTodo("New Task")}>Add Todo</button>
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
</div>
);
}

✅ Now, todos sync automatically across multiple users! 🎉

✅ Example 2: Live Counter with CRDT Sync

This ensures counter updates don’t get lost when multiple users increment at the same time.

🔹 Step 1: Setup WebSocket for Syncing (src/socket/websocket.ts):

src/socket/websocket.ts
import { counterState } from "../components/Counter"
const socket = new WebSocket("ws://localhost:4000");

socket.onmessage = (event) => {
const { key, data } = JSON.parse(event.data);
if (key === "counter") syncCRDT(data, counterState);
};

export const syncCounter = (state) => {
socket.send(JSON.stringify({ key: "counter", data: state }));
};

🔹 Step 2: Use CRDT in src/components/Counter.tsx:

src/components/Counter.tsx
import { useStateGlobal, syncCRDT } from "state-jet";
import { syncCounter } from "../socket/websocket";

export const counterState = useStateGlobal("counter", { value: 0, lastUpdated: Date.now() });

export default function Counter() {
const counter = counterState.useState();

const increment = () => {
const updatedCounter = { value: counter.value + 1, lastUpdated: Date.now() };
syncCRDT(updatedCounter, counterState);
syncCounter(updatedCounter); // Send update to WebSocket
};

return (
<div>
<h1>Live Counter: {counter.value}</h1>
<button onClick={increment}>Increment</button>
</div>
);
}

✅ Now, multiple users can increment the counter without conflicts! 🎉

✅ Example 3: Real-Time Collaborative Notes

This syncs text changes across users with CRDT conflict resolution.

🔹 Step 1: WebSocket Sync for Notes (src/socket/websocket.ts):

src/socket/websocket.ts
import { noteState } from "../components/Notes"
const socket = new WebSocket("ws://localhost:4000");

socket.onmessage = (event) => {
const { key, data } = JSON.parse(event.data);
if (key === "notes") syncCRDT(data, noteState);
};

export const syncNotes = (state) => {
socket.send(JSON.stringify({ key: "notes", data: state }));
};

🔹 Step 2: Use CRDT in src/components/Notes.tsx:

src/components/TodoApp.tsx
import { useStateGlobal, syncCRDT } from "state-jet";
import { syncNotes } from "../socket/websocket";

export const noteState = useStateGlobal("notes", { content: "", lastUpdated: Date.now() });

export default function Notes() {
const note = noteState.useState();

const updateNote = (e) => {
const updatedNote = { content: e.target.value, lastUpdated: Date.now() };
syncCRDT(updatedNote, noteState);
syncNotes(updatedNote); // Send update to WebSocket
};

return (
<div>
<h1>Collaborative Notes</h1>
<textarea value={note.content} onChange={updateNote} />
</div>
);
}

✅ Now, multiple users can edit notes at the same time without conflicts! 🎉

🎯 Why Use syncCRDT?

FeatureWithout syncCRDTWith syncCRDT
Multi-User SyncPossible Conflicts✅ Automatic Merging
Real-Time UpdatesNeeds Manual Fixes✅ No Data Loss
Handles ConflictsCan Lose Changes✅ Merges Automatically
Scalable for TeamsHard to Maintain✅ Ideal for Collaboration