小编典典

MobX-在将数据注入到React组件时可以使用`inject`时为什么要使用`observer`

reactjs

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

我的理解是,有了observer,即使上一个可观察的对象嵌套在数据存储区的深处,最后一次渲染中所有访问的可观察的对象的更改都将导致重新渲染,而inject只有在注入器函数中访问的可观察对象发生更改时才重新渲染。

例如:

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 {  }

有人可以确认我对此的理解吗?

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

当一个在另一个上使用时,还有其他好处/缺点吗?


阅读 716

收藏
2020-07-22

共1个答案

小编典典

我相信您的评估是正确的。为了清楚起见,让我尝试重新措辞:

@observerrender当这些值之一更改时,跟踪哪些可观察对象由组件使用并自动重新渲染。

我们应该注意,根据您的示例,@observable使用的值render可能深深嵌套在给定的值中prop

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

使用观察者,即使上一个可观察的对象嵌套在数据存储区的深处,最后一次渲染中所有访问的可观察的对象的更改也将导致重新渲染

答对了!

尽管会有一个奇怪的地方observable,稍后您会看到…


另一方面,您有@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仅当prop自身已识别出更改时才生成重新渲染。


实际上,shouldComponentUpdate()和-的深度比较实际上是相同的问题,props尽管它observer似乎比效率更高shouldComponentUpdate

我认为,最好仅使用注入,因为它可以为您提供更多控制权,并且可以防止不必要的重新渲染。

我并不一定要走那么远……这完全取决于您的代码结构。

如果我这样修改您的原始示例:

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

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

…添加的deepDataw实际上不会作为可观察的变化(即重新渲染)被拾取,因为当我们最初将其标记data为可观察的值时,该属性不存在。这是一个问题。

另一种方法可能是执行以下操作:

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

class Store{
    @observable data = null;

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

这使您可以将可观察的值分散到各个类中-
因此您可能仍想注入Store一个组件(以进行访问,Store.data但最终所有可观察的更改都来自更新Person

2020-07-22