Leo Jiang
Leo Jiang

Reputation: 26085

Listening for array changes using MobX

I just started learning MobX today and I want to listen for all array changes (insertion, deletion, etc) using MobX. An example would illustrate this better:

const TodoList = ({todos}) => (
    <ul>
        {todos.map(todo => <li key={todo.id}>
            <TodoContainer todo={todo}/>
        </li>)}
    </ul>
);

module.exports = @observer class TodoListContainer extends React.Component {
    static contextTypes = {
        todoStore: React.PropTypes.instanceOf(TodoStore),
    };

    render() {
        let todos = this.context.todoStore.getTodos();

        return <TodoList todos={todos}/>;
    }
}

If I add or remove an item from todos, the list isn't updated. In order to make it update, I need to wrap observer around TodoList. The @observer on TodoListContainer doesn't do anything because I'm not accessing any observed properties. However, just for learning purposes, I want to use observer only on containers. I want to make the container rerender every time todos changes.

One way to do this is to do anything in TodoListContainer that iterates through all of todos. For example, in TodoListContainer.render, I can add for (let todo of todos) {} or todos.forEach(_ => _). Is there a better way to do it? For example, in Ember Data, you can do todos.[] to represent listening to all changes in todos.

Upvotes: 1

Views: 1239

Answers (1)

Mouad Debbar
Mouad Debbar

Reputation: 3226

The container component doesn't know exactly what data TodoList is accessing. In your example, it's looping through the array and accessing the id attribute of each todo object. MobX is smart at tracking changes. So if, for example, you change the id of the 3rd todo item: todoStore.getTodos()[2].id = 3;, MobX will rerender TodoList even though no item was added or removed from the array.

In general, I'd recommend adding @observer to all components and let MobX take care of tracking/rerendering.

Upvotes: 1

Related Questions