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

How to use MobX's observer in React?

2月19日 17:58

In MobX, observer is a Higher-Order Component (HOC) used to convert React components into reactive components. When the data used by a component changes, the component automatically re-renders.

Basic Usage of observer

1. Using observer with Class Components

javascript
import React from 'react'; import { observer } from 'mobx-react'; import { observable } from 'mobx'; class Store { @observable count = 0; } const store = new Store(); @observer class Counter extends React.Component { render() { return ( <div> <p>Count: {store.count}</p> <button onClick={() => store.count++}>Increment</button> </div> ); } }

2. Using observer with Functional Components

javascript
import React from 'react'; import { observer } from 'mobx-react-lite'; import { observable } from 'mobx'; class Store { @observable count = 0; } const store = new Store(); const Counter = observer(() => { return ( <div> <p>Count: {store.count}</p> <button onClick={() => store.count++}>Increment</button> </div> ); });

How observer Works

1. When Component Mounts

  • MobX creates a reaction to track all observables accessed in the component's render function
  • Establishes dependency relationships between the component and observables

2. When State Changes

  • When an observable is modified, MobX detects the dependency change
  • Marks the component as needing re-render
  • In the next event loop, triggers the component's re-render

3. When Component Unmounts

  • Automatically cleans up reactions and dependency relationships
  • Avoids memory leaks

observer's Optimization Features

1. Fine-grained Updates

observer only re-renders components that truly need updating:

javascript
@observer class Parent extends React.Component { render() { return ( <div> <ChildA /> <ChildB /> </div> ); } } @observer class ChildA extends React.Component { render() { // Only depends on store.count return <div>Count: {store.count}</div>; } } @observer class ChildB extends React.Component { render() { // Only depends on store.name return <div>Name: {store.name}</div>; } }

When store.count changes, only ChildA will re-render, not ChildB.

2. shouldComponentUpdate Optimization

observer automatically implements shouldComponentUpdate to avoid unnecessary renders:

  • Only re-renders when observables the component depends on actually change
  • Even if the parent component re-renders, child components may not re-render

3. Batched Updates

Multiple state changes are batched and trigger only one re-render:

javascript
runInAction(() => { store.count++; store.name = 'New Name'; });

Best Practices for observer

1. Only Use observer Where Needed

Not all components need observer, only use it on components that need to respond to state changes:

javascript
// Doesn't need observer const Header = () => <h1>My App</h1>; // Needs observer const Counter = observer(() => { return <div>Count: {store.count}</div>; });

2. Avoid Creating New Objects in render

Creating new objects in render causes unnecessary re-renders:

javascript
// Bad practice const BadComponent = observer(() => { const style = { color: 'red' }; // Creates new object every render return <div style={style}>{store.count}</div>; }); // Good practice const style = { color: 'red' }; // Define outside component const GoodComponent = observer(() => { return <div style={style}>{store.count}</div>; });

3. Use computed to Optimize Calculations

Use computed outside the component to optimize calculation logic:

javascript
// Bad practice const BadComponent = observer(() => { const fullName = `${store.firstName} ${store.lastName}`; return <div>{fullName}</div>; }); // Good practice class Store { @observable firstName = 'John'; @observable lastName = 'Doe'; @computed get fullName() { return `${this.firstName} ${this.lastName}`; } } const GoodComponent = observer(() => { return <div>{store.fullName}</div>; });

4. Use React.memo with observer

For pure presentation components, you can combine with React.memo:

javascript
const PureComponent = React.memo(observer(() => { return <div>{store.count}</div>; }));

Common Issues

1. Component Not Updating

Ensure:

  • Component is wrapped with observer
  • Accessing observables, not plain objects
  • State modifications are done in actions

2. Over-rendering

If component over-renders, check:

  • Are new objects being created in render?
  • Is computed being used to optimize calculations?
  • Can the component be split to reduce dependencies?

3. Memory Leaks

Ensure:

  • observer automatically cleans up when component unmounts
  • Manually created reactions need manual cleanup

Summary

observer is the core of MobX and React integration, achieving efficient reactive updates through fine-grained dependency tracking. Using observer correctly and following best practices can build high-performance React applications.

标签:ReactMobx