So let’s say i have a todoStore. It has an action that deletes a todo by id. Note that i tried both filter and splice:
export default class TodosStore { constructor() { makeAutoObservable(this) } todos = [ { id: 1, name: "name1", completed: true }, { id: 15, name: "name2", completed: true }, { id: 14, name: "name3", completed: true } ] removeTodo(id) { // this.todos = this.todos.filter(todo=>todo.id != id) for (let todo of this.todos) { if (todo.id == id) { const indexOf = this.todos.indexOf(todo) this.todos.splice(indexOf, 1) } } } };
The consuming Todos component(Note that i’m wrapping the Todo with observer):
import { combinedStores } from "." const ObservableTodo = observer(Todo); export default observer(() => { const { todosStore } = combinedStores return ( <div > {todosStore.todos.map(todo=>{ return( <ObservableTodo onDelete={()=>{todosStore.removeTodo(todo.id)}} onNameChange={(value)=>{todosStore.editTodoName(todo.id,value)}} key={todo.id} todo={todo}></ObservableTodo> ) })} </div> ) })
The simple Todo component:
export default ({todo,onNameChange,onDelete}) => { return ( <div style={{padding:'10px',margin:'10px'}}> <p>ID: {todo.id}</p> <input onChange={(e)=>{onNameChange(e.target.value)}} value={todo.name}></input> <p>Completed: {todo.completed ? 'true' : 'false'} <button onClick={onDelete} className="btn btn-danger">Delete</button></p> </div> ) }
Even though i’m clearly mutating(as opposed to constructing a new array) the todos array within the store, Todos component rerenders(i see it via console.logs), and so does every remaining Todo component.
Is there any way around it? Is there anything wrong with my setup perhaps? I’m using latest Mobx(6) and mobx-react.
Advertisement
Answer
Todos
component is supposed to rerender because it depends on todos
array content (because it map
‘s over it). So when you change todos
content by adding or removing some todo – Todos
component will rerender because it needs to render new content, new list of todos.
Each single Todo
rerenders because you have not wrapped it with observer
. It is a good practice to wrap every component which uses some observable state, and Todo
is clearly the one that does.