乐闻世界logo
搜索文章和话题

What are the important changes in MobX 6 compared to MobX 4/5?

2月22日 14:08

MobX 6 is the latest major version of MobX, with many important changes and improvements compared to MobX 4/5. Understanding these changes is important for upgrading and maintaining projects.

Major Changes

1. Removed Decorator Support

MobX 6 no longer supports decorator syntax by default, recommending the use of makeObservable or makeAutoObservable.

MobX 4/5 (Decorator Syntax):

javascript
import { 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 }); } }

MobX 6 (Recommended):

javascript
import { 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 }); } }

2. makeObservable and makeAutoObservable

MobX 6 introduced two new APIs to replace decorators:

makeObservable

Need to explicitly specify the type of each property.

javascript
import { 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 }); } }

makeAutoObservable (Recommended)

Automatically infer property types, more concise.

javascript
import { 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 }); } }

3. Removed configure

MobX 6 removed the configure API, no longer requiring global configuration.

MobX 4/5:

javascript
import { configure } from 'mobx'; configure({ enforceActions: 'always', useProxies: 'ifavailable' });

MobX 6:

javascript
// No longer need configure, default behavior has been optimized

4. Removed extras

MobX 6 removed the extras API, related features have been integrated into the main API.

MobX 4/5:

javascript
import { extras } from 'mobx'; const isObservable = extras.isObservable(obj);

MobX 6:

javascript
import { isObservable } from 'mobx'; const isObservable = isObservable(obj);

5. Removed intercept and observe

MobX 6 removed the intercept and observe APIs, recommending the use of reaction instead.

MobX 4/5:

javascript
import { observe } from 'mobx'; const disposer = observe(store.todos, (change) => { console.log('Todo changed:', change); });

MobX 6:

javascript
import { reaction } from 'mobx'; const disposer = reaction( () => store.todos.length, (length) => { console.log('Todo count changed:', length); } );

6. Improved Type Inference

MobX 6 has better support for TypeScript with more accurate type inference.

typescript
import { makeAutoObservable } from 'mobx'; class TodoStore { todos: Todo[] = []; filter: 'all' | 'completed' | 'active' = 'all'; constructor() { makeAutoObservable<TodoStore>(this); } get completedTodos(): Todo[] { return this.todos.filter(todo => todo.completed); } addTodo(text: string): void { this.todos.push({ text, completed: false }); } }

7. Removed inject and Provider from mobx-react

MobX 6 recommends using React Context API, no longer needing inject and Provider.

MobX 4/5:

javascript
import { Provider, inject, observer } from 'mobx-react'; @inject('todoStore') @observer class TodoList extends React.Component { render() { const { todoStore } = this.props; return <div>{/* ... */}</div>; } } function App() { return ( <Provider todoStore={todoStore}> <TodoList /> </Provider> ); }

MobX 6:

javascript
import { observer } from 'mobx-react-lite'; import { createContext, useContext } from 'react'; const TodoContext = createContext(null); function TodoProvider({ children, store }) { return ( <TodoContext.Provider value={store}> {children} </TodoContext.Provider> ); } function useTodoStore() { const store = useContext(TodoContext); if (!store) { throw new Error('useTodoStore must be used within TodoProvider'); } return store; } const TodoList = observer(() => { const store = useTodoStore(); return <div>{/* ... */}</div>; }); function App() { return ( <TodoProvider store={todoStore}> <TodoList /> </TodoProvider> ); }

8. Performance Improvements

MobX 6 has many performance improvements:

  1. Smaller bundle size: Reduced bundle size through Tree-shaking
  2. Faster response: Optimized dependency tracking algorithm
  3. Better memory management: Reduced memory usage

9. Improved Error Handling

MobX 6 provides clearer error messages.

javascript
// MobX 6 provides clearer error messages class Store { data = []; constructor() { makeAutoObservable(this); } // If modifying state outside action modifyData() { this.data.push({}); // Warning: modifying state outside action } }

Migration Guide

Migrating from MobX 4/5 to MobX 6

1. Remove Decorators

Before:

javascript
class Store { @observable data = []; @action addData(item) { this.data.push(item); } }

After:

javascript
class Store { data = []; constructor() { makeAutoObservable(this); } addData(item) { this.data.push(item); } }

2. Update mobx-react

Before:

javascript
import { Provider, inject, observer } from 'mobx-react'; @inject('store') @observer class Component extends React.Component { render() { const { store } = this.props; return <div>{store.data}</div>; } }

After:

javascript
import { observer } from 'mobx-react-lite'; const Component = observer(() => { const store = useStore(); return <div>{store.data}</div>; });

3. Remove configure

Before:

javascript
import { configure } from 'mobx'; configure({ enforceActions: 'always' });

After:

javascript
// No longer need configure

4. Update extras

Before:

javascript
import { extras } from 'mobx'; if (extras.isObservable(obj)) { // ... }

After:

javascript
import { isObservable } from 'mobx'; if (isObservable(obj)) { // ... }

Best Practices

1. Use makeAutoObservable

javascript
class Store { data = []; constructor() { makeAutoObservable(this); } }

2. Use mobx-react-lite

javascript
import { observer } from 'mobx-react-lite'; const Component = observer(() => { return <div>{/* ... */}</div>; });

3. Use React Context

javascript
const StoreContext = createContext(null); function StoreProvider({ children, store }) { return ( <StoreContext.Provider value={store}> {children} </StoreContext.Provider> ); } function useStore() { const store = useContext(StoreContext); if (!store) { throw new Error('useStore must be used within StoreProvider'); } return store; }

4. Use TypeScript

typescript
class Store { data: Data[] = []; constructor() { makeAutoObservable<Store>(this); } }

Common Questions

1. How to continue using decorators?

If you need to continue using decorators, you can install the mobx-undecorate package.

javascript
import { decorate, observable, action } from 'mobx'; class Store { data = []; addData(item) { this.data.push(item); } } decorate(Store, { data: observable, addData: action });

2. How to handle type inference?

When using makeAutoObservable, you can pass a generic parameter.

typescript
class Store { data: Data[] = []; constructor() { makeAutoObservable<Store>(this); } }

3. How to handle action.bound?

When using action.bound, you need to specify it in makeObservable.

javascript
class Store { data = []; constructor() { makeObservable(this, { data: observable, addData: action.bound }); } addData(item) { this.data.push(item); } }

Summary

  • MobX 6 removed decorator support, recommending the use of makeAutoObservable
  • Removed configure, extras, intercept, observe and other APIs
  • Recommend using mobx-react-lite and React Context
  • Better support for TypeScript
  • Improvements in performance and error handling
  • Migration is relatively simple, mainly replacing decorator syntax
标签:Mobx