javascript – MobX – 当我将数据注入React组件时可以使用`inject`时,我为什么要使用`observer`

MobX文档建议我应该在所有组件上使用observer.但是,通过使用注入,我可以更精细地控制哪些数据导致重新呈现我的组件.

我的理解是,对于观察者来说,即使observable嵌套在数据存储的深处,最后渲染中所有被访问的observable的更改也会导致重新渲染,而当注入器函数中访问observable时,只注入重新渲染更改.

例如:

class Store{
  @observable data = {
    nestedData: {
      deepData: 'my_data'
    }
  }
}

const store = new Store();

... Assume the store is injected using <Provider /> component

// This will cause re-render when the data object changes
// for example: store.data = { new_data: 'new_data' }
@inject(stores => {
  return { data: stores.dataStore.data }; 
})
class MyComponent extends Component {  }

// This will re-render on change of the data object, but also
// on change of nestedData and deepData properties
@inject(stores => {
  return { data: stores.dataStore.data }; 
})
@observer
class MyComponent extends Component {  }

有人可以证实我对此的理解吗?

在我看来,最好只使用注入,因为它可以提供更多控制,并且可以防止不必要的重新渲染.如果数据是深度嵌套的,您可以创建一个计算属性,从深层结构获取并准备数据,然后在组件中注入该属性.

使用一个优于另一个时是否存在其他优点/缺点

解决方法:

我相信你的评估是正确的.让我试着澄清一下:

@observer跟踪渲染使用哪些可观察对象,并在其中一个值发生更改时自动重新渲染组件.

我们应该注意到,根据你的例子,render使用的@observable值可能会深深嵌套在给定的prop中:

class Store{
  @observable data = {
    nestedData: {
      // changes to `deepData` would theoretically re-render any observer
      deepData: 'my_data' 
    }
  }
}

with observer, a change in all accessed
observables in the last render will cause a re-render, even if the
observable is nested deep in the data store

答对了!

虽然有一个可观察的怪癖,你马上就会看到……

另一方面,您拥有@inject,它可以为组件(通过props)提供由Provider定义的特定数据结构.

例如:

@inject('title')
class MyComponent extends React.Component {
    render() {
        return (<div>{this.props.title}</div>);
    }
}

const Container = () => (
    <Provider title="This value is passed as a prop using `inject`">
        <MyComponent />
    </Provider>
);

inject only
re-renders when observables accessed in the injector function change.

答对了!

如果prop本身已经识别出更改,则inject将仅生成重新渲染.

这与shouldComponentUpdate()和道具的深度比较实际上是相同的问题 – 尽管观察者似乎是far more efficient而不是shouldComponentUpdate.

In my opinion, it’s better to use only inject as it gives you more
control, and can prevent unnecessary re-renders.

我不一定会走得那么远……这完全取决于你如何构建代码.

如果我修改原始示例:

class Store{
    @observable data = {
        nestedData: {}
    };

    constructor() {
        this.data.nestedData.deepData = 'my_data';
    }
}

…添加deepData实际上不会被视为可观察的更改(即重新渲染),因为当我们最初将数据标记为可观察值时,该属性不存在.这是一个问题.

一种不同的方法可能是做这样的事情:

class Person {
    @observable name = 'John Doe';
}

class Store{
    @observable data = null;

    constructor() {
        this.data = new Person();
    }
}

这允许您跨类传播可观察值 – 因此您可能仍希望将Store注入组件(访问Store.data,但最终任何可观察到的更改都来自更新Person.

上一篇:在香草ES6 Javascript类中访问MobX存储


下一篇:Object类学习