"解密 状态管理 MobX:组件更新的秘密与陷阱"

443 阅读2分钟

在使用 MobX 和 React 的 observer 组件时,MobX 的响应机制决定了何时会更新组件。在以下情况下,修改值会导致组件更新或不会更新:

组件会更新的情况

  1. 直接修改可观察属性:

    • 当你直接修改一个 MobX 的可观察属性时,任何依赖该属性的 observer 组件都会自动重新渲染。
    import { observable } from 'mobx';
    import { observer } from 'mobx-react';
    
    class Store {
        @observable counter = 0;
    
        increment() {
            this.counter += 1; // 更改可观察属性
        }
    }
    
    const store = new Store();
    
    const CounterComponent = observer(() => {
        return (
            <div>
                <p>Counter: {store.counter}</p>
                <button onClick={() => store.increment()}>Increment</button>
            </div>
        );
    });
    
  2. 计算值的变化:

    • 当所依赖的计算值被更改时。如果一个 observer 组件依赖于某个计算值,且计算值的依赖发生变化,则该组件会更新。
    import { computed } from 'mobx';
    
    class Store {
        @observable numbers = [1, 2, 3];
    
        @computed get sum() {
            return this.numbers.reduce((acc, num) => acc + num, 0);
        }
    }
    
    const store = new Store();
    
    const SumComponent = observer(() => {
        return <div>Sum: {store.sum}</div>; // 依赖计算值
    });
    
  3. 使用 autorun 和 reaction:

    • 在 MobX 中,使用 autorun 和 reaction 处理的副作用会在其依赖发生变化时自动触发。
    import { reaction } from 'mobx';
    
    reaction(
        () => store.counter,
        (counter) => {
           console.log(`Counter changed: ${counter}`);
        }
    );
    

组件不会更新的情况

  1. 未定义为可观察的属性:

    • 如果你修改了一个非可观察的属性,依赖该属性的组件不会重新渲染。例如,对于类中的普通属性,MobX 无法跟踪其变化。
    class Store {
        counter = 0; // 非可观察属性
    
        increment() {
            this.counter += 1; // 改变非可观察属性,不会触发更新
        }
    }
    
  2. 使用 props:

    • 如果 observer 组件的 props 未处于可观察状态并且未被修改,即使其父组件的状态发生变化,该组件也不会更新。
  3. 直接修改数组对象而未使用 MobX 的方法:

    • 如果你直接修改 MobX 可观察数组的内容而不是使用 MobX 提供的方法来更新数组(如 pushsplice 等),可能会导致组件不更新。
    class Store {
        @observable items = [];
    
        updateItem(id, newValue) {
            const item = this.items.find(i => i.id === id);
            item.value = newValue; // 直接修改对象属性,不会触发更新
            // 应该使用 `this.items` 的方法,如:`this.items = [...this.items];` 重新创建引用
        }
    }
    
  4. 深层嵌套的对象:

    • 对于嵌套的可观察对象,若你不使用 MobX 的 @observable 装饰器标记内部属性,或者未在组件中显式访问这些属性,该组件可能不会响应更新。
  5. 不使用 observer:

    • 如果组件没有被 observer 装饰,虽然内部状态变化,但组件本身不会更新。

总结

在使用 MobX 和 Observer 组件时,关键是确保你对状态的修改准确且遵循 MobX 的响应式设计原则。确保可观察的属性被正确设置,使用合适的方法更改状态,以及要注意深层嵌套的数据结构。当遵循这些原则时,MobX 将做到高效且自动化组件更新。