본문 바로가기

배워서 따라하는 포플/react-mobx를 이용한 앱

Todo 앱 만들기

npx create-react-app ./ --template typescript
npm install mobx mobx-react

위 명령어를 통해 typescript인 react과 mobx를 설치합니다.

import { action, computed, makeObservable, observable } from 'mobx';

interface TodoItem {
  id: number;
  title: string;
  completed: boolean;
}

export default class TodoStore {
  todos: TodoItem[] = []

    constructor() {
      makeObservable(this, {
        todos: observable,
        addTodo: action,
        toggleTodo: action,
        status: computed
    })
  }

  addTodo(title: string) {
    const item: TodoItem = {
        id: getId(),
        title: title,
        completed: false,
    }
    this.todos.push(item)
  }

  toggleTodo(id: number) {
    const index = this.todos.findIndex((item) => item.id === id);
    if (index > -1) {
        this.todos[index].completed = !this.todos[index].completed;
        console.log('this.todos[index]', this.todos[index].completed)
    }
  }

  get status() {
    let completed = 0, remaining = 0
    this.todos.forEach((todo) => {
        if (todo.completed) {
            completed++
        } else {
            remaining++
        }
    })

    return { completed, remaining }
  }
}

let id = 0;
function getId() {
    return id++;
}

TodoStore.ts 파일의 코드입니다.

 

UI 작업하기

import { observer } from 'mobx-react'
import React, { useState } from 'react'
import TodoStore from './TodoStore'

interface TodoListProps {
  todoStore: TodoStore;
}

const TodoList: React.FC<TodoListProps> = observer( ({todoStore}) => {

  const [value, setValue] = useState<string>('')

  return (
    <div>
      <input
        value={value}
        onChange={(e) => {
          setValue(e.target.value)
        }}
        type='text'
      />
      <button
        onClick={() => {
          if(value) {
            todoStore.addTodo(value)
          }
          setValue('')
        }}
      >
        Add
      </button>

      <div>Completed: {todoStore.status.completed}</div>
      <div>Remaining: {todoStore.status.remaining}</div>

      <ul>
        {todoStore.todos.map(todo => {
          return (
            <li 
              key={todo.id}
              onClick={() => {
                todoStore.toggleTodo(todo.id)
              }}
            >
              {todo.title} [{todo.completed ? 'x' : ' '}]
            </li>
          )
        })}
      </ul>
    </div>
  )
})

export default TodoList

TodoList.ts 파일의 코드입니다.

App.tsx의 변경 코드입니다.