MobX - Почему я должен использовать «наблюдатель», когда я могу использовать «инъекцию» при вводе данных в компонент React

Документация MobX предлагает мне использовать observer на всех моих компонентах. Однако, используя Inject, я получаю более детальный контроль над тем, какие данные вызывают повторную визуализацию моих компонентов.

Я понимаю, что при использовании 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, так как это дает вам больше контроля и может предотвратить ненужные повторные рендеры. Если данные глубоко вложены, вы можете создать вычисляемое свойство, которое получает и подготавливает данные из глубокой структуры, а затем вставляет это свойство в компонент.

Есть ли другие преимущества /недостатки при использовании одного над другим

4 голоса | спросил Mateo Hrastnik 25 Jam1000000amThu, 25 Jan 2018 09:48:11 +030018 2018, 09:48:11

1 ответ


0

Я считаю, что вы правы в своей оценке. Позвольте мне перефразировать для ясности:

@observer отслеживает, какие наблюдаемые используются render, и автоматически выполняет повторную визуализацию компонента при изменении одного из этих значений.

Следует отметить, что значения @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';
    }
}

... добавление deepData фактически не воспринимается как наблюдаемое изменение (то есть повторное отображение), потому что это свойство не существовало, когда мы изначально помечали data как наблюдаемое значение. Так что это одна проблема.

Другой подход может заключаться в следующем:

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

class Store{
    @observable data = null;

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

Это позволяет вам распределять наблюдаемые значения по классам - так что вы все равно можете добавить Store в компонент (для получить доступ Store.data, но в конечном итоге любые заметные изменения происходят из-за обновления Person

ответил arthurakay 27 Jam1000000amSat, 27 Jan 2018 00:10:22 +030018 2018, 00:10:22

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132