Hi guys i was just trying out mobx today and made a Todo List with it, the problem is the list isn't updating here after the item is removed from the list even though i had made observer and observable. You can also directly check my code here at CodeSanbox .It's a basic todo app
Store.js
import { observable, action, computed, reaction } from "mobx"
import { createContext } from "react"
import { v4 as uuidv4 } from 'uuid';
export interface Todo {
id?: string;
title: string;
completed: boolean;
}
class TodoStore {
constructor() {
reaction(() => this.todos, _ => console.log(this.todos.length))
}
@observable todos: Todo[] = [
{ id: uuidv4(), title: "Item #1", completed: false },
{ id: uuidv4(), title: "Item #2", completed: false },
{ id: uuidv4(), title: "Item #3", completed: false },
{ id: uuidv4(), title: "Item #4", completed: false },
{ id: uuidv4(), title: "Item #5", completed: true },
{ id: uuidv4(), title: "Item #6", completed: false },
]
@action addTodo = (todo: Todo) => {
this.todos.push({ ...todo, id: uuidv4() })
}
@action toggleTodo = (id: string) => {
this.todos = this.todos.map(todo => {
if (todo.id === id) {
return {
...todo,
completed: !todo.completed,
}
}
return todo
})
}
@action removeTodo = (id: string) => {
console.log(id)
this.todos = this.todos.filter(todo => todo.id !== id)
console.log(this.todos)
}
@computed get info() {
return {
total: this.todos.length,
completed: this.todos.filter(todo => todo.completed).length,
notCompleted: this.todos.filter(todo => !todo.completed).length,
}
}
}
export default createContext(new TodoStore())
TodoList.js
import React, { useContext } from "react";
import TodoStore from "../stores/TodoStore";
import { observer } from "mobx-react-lite";
const TodoList = () => {
const todoStore = useContext(TodoStore);
const { todos, toggleTodo, removeTodo } = todoStore;
return (
<>
<div className="row">
<table className="table table-hover">
<thead className="thead-light">
<tr>
<th>Title</th>
<th>Completed?</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{todos.map(todo => (
<tr key={todo.id}>
<td>{todo.title}</td>
<td>{todo.completed ? "✅" : ""}</td>
<td>
<button
className="btn btn-sm btn-info"
onClick={_ => toggleTodo(todo.id!)}
>
Toggle
</button>
<button
className="btn btn-sm btn-danger"
onClick={_ => removeTodo(todo.id!)}
>
Remove
</button>
</td>
</tr>
))}
</tbody>
</table>
</div>
</>
);
};
export default observer(TodoList);
So as i click remove button, the action "removeTodo" gets fired up the todo is removed from the list i can check that on console but it istn't updating in the UI part
With Mobx v6
simply setting decorators
is not enough anymore. You also need to call makeObservable
or makeAutoObservable
in the class constructor.
import { observable, action, computed, reaction,makeAutoObservable } from "mobx"
constructor() {
makeAutoObservable(this)
reaction(() => this.todos, _ => console.log(this.todos.length))
}