In MobX, observable is one of the core concepts that converts ordinary JavaScript objects, arrays, Maps, Sets, and other data structures into observable objects, enabling MobX to track their changes.
Observable Usage Methods
1. Using Decorators
javascriptimport { observable, action, computed } from 'mobx'; class TodoStore { @observable todos = []; @observable filter = 'all'; @computed get completedTodos() { return this.todos.filter(todo => todo.completed); } @action addTodo(text) { this.todos.push({ text, completed: false }); } }
2. Using makeObservable
javascriptimport { makeObservable, observable, action, computed } from 'mobx'; class TodoStore { todos = []; filter = 'all'; constructor() { makeObservable(this, { todos: observable, filter: observable, completedTodos: computed, addTodo: action }); } get completedTodos() { return this.todos.filter(todo => todo.completed); } addTodo(text) { this.todos.push({ text, completed: false }); } }
3. Using makeAutoObservable (Recommended)
javascriptimport { makeAutoObservable } from 'mobx'; class TodoStore { todos = []; filter = 'all'; constructor() { makeAutoObservable(this); } get completedTodos() { return this.todos.filter(todo => todo.completed); } addTodo(text) { this.todos.push({ text, completed: false }); } }
4. Using observable Function
javascriptimport { observable } from 'mobx'; const state = observable({ todos: [], filter: 'all' }); const completedTodos = observable(() => state.todos.filter(todo => todo.completed) );
Observable Features
1. Automatic Dependency Tracking
When an observable object is read, MobX automatically establishes dependency relationships.
javascriptimport { observable, autorun } from 'mobx'; const store = observable({ count: 0 }); autorun(() => { console.log('Count is:', store.count); }); store.count = 1; // Automatically triggers autorun
2. Deep Observability
observable is deep observable by default, recursively converting all properties of an object to observable.
javascriptconst store = observable({ user: { name: 'John', address: { city: 'New York' } } }); store.user.address.city = 'Boston'; // Will be tracked
3. Special Handling for Arrays and Maps
observable arrays and Maps provide additional APIs while maintaining compatibility with native APIs.
javascriptconst list = observable([1, 2, 3]); list.push(4); // MobX will track this change list.splice(0, 1); // Will also be tracked
Observable Configuration Options
1. shallow (Shallow Observable)
Only track changes to the object itself, not nested objects.
javascriptimport { observable } from 'mobx'; const store = observable({ user: { name: 'John' } }, {}, { deep: false }); store.user = { name: 'Jane' }; // Will be tracked store.user.name = 'Bob'; // Will not be tracked
2. asMap, asArray
Explicitly specify data structure types.
javascriptconst map = observable.map({ key: 'value' }); const array = observable.array([1, 2, 3]);
Important Notes
- Do not modify observable state outside of actions
- Avoid using decorators in constructor
- Use computed reasonably to cache calculation results
- Consider using shallow for large objects to optimize performance
- observable objects cannot be frozen (Object.freeze)
Best Practices
- Prioritize using
makeAutoObservableto simplify configuration - Use
observablefunction for simple state - Use class + decorators or
makeObservablefor complex state management - Use computed reasonably to avoid repeated calculations
- Always modify observable state in actions