TodoMVC
This is an example of real-time collaborative TodoMVC using CreatReactApp and Yorkie JS SDK.
App.tsx
1import React, { useState, useEffect } from 'react';2import yorkie, { Document, JSONArray } from 'yorkie-js-sdk';3import 'todomvc-app-css/index.css';45import Header from './Header';6import MainSection from './MainSection';7import { Todo } from './model';8import './App.css';910const initialState = [{11 id: 0,12 text: 'Yorkie JS SDK',13 completed: false,14}, {15 id: 1,16 text: 'Garbage collection',17 completed: false,18}, {19 id: 2,20 text: 'RichText datatype',21 completed: false,22}] as Array<Todo>;2324export default function App() {25 const [doc,] = useState<Document<{ todos: JSONArray<Todo> }>>(() =>26 new yorkie.Document<{ todos: JSONArray<Todo> }>('react-todomvc')27 );28 const [todos, setTodos] = useState<Array<Todo>>([]);2930 const actions = {31 addTodo: (text: string) => {32 doc?.update((root) => {33 root.todos.push({34 id: root.todos.reduce((maxId, todo) => Math.max(todo.id, maxId), -1) + 1,35 completed: false,36 text,37 });38 });39 },40 deleteTodo: (id: number) => {41 doc?.update((root) => {42 let target;43 for (const todo of root.todos) {44 if (todo.id === id) {45 target = todo as any;46 break;47 }48 }49 if (target) {50 root.todos.deleteByID!(target.getID());51 }52 });53 },54 editTodo: (id: number, text: string) => {55 doc?.update((root) => {56 let target;57 for (const todo of root.todos) {58 if (todo.id === id) {59 target = todo;60 break;61 }62 }63 if (target) {64 target.text = text;65 }66 });67 },68 completeTodo: (id: number) => {69 doc?.update((root) => {70 let target;71 for (const todo of root.todos) {72 if (todo.id === id) {73 target = todo;74 break;75 }76 }77 if (target) {78 target.completed = !target.completed;79 }80 });81 },82 clearCompleted: () => {83 doc?.update((root) => {84 for (const todo of root.todos) {85 if (todo.completed) {86 const t = todo as any;87 root.todos.deleteByID!(t.getID());88 }89 }90 }, '');91 }92 };9394 useEffect(() => {95 const client = new yorkie.Client(import.meta.env.VITE_YORKIE_API_ADDR, {96 apiKey: import.meta.env.VITE_YORKIE_API_KEY,97 });9899 async function attachDoc(doc: Document<{ todos: JSONArray<Todo> }>, callback: (todos: any) => void) {100 // 01. create client with RPCAddr(envoy) then activate it.101 await client.activate();102103 // 02. attach the document into the client.104 await client.attach(doc);105106 // 03. create default todos if not exists.107 doc.update((root) => {108 if (!root.todos) {109 root.todos = initialState;110 }111 }, 'create default todos if not exists');112113 // 04. subscribe change event from local and remote.114 doc.subscribe((event) => {115 callback(doc.getRoot().todos);116 });117118 // 05. set todos the attached document.119 callback(doc.getRoot().todos);120 }121122 attachDoc(doc, (todos) => {123 setTodos(todos);124 });125 }, []);126127 return (128 <div className="App">129 <Header addTodo={actions.addTodo} />130 <MainSection todos={todos} actions={actions} />131 </div>132 );133}
- User 1
- User 2
- User 1
- User 2
Event Log