Магазин MobX не обновляется в ответ - PullRequest
0 голосов
/ 12 июня 2018

Чего я хочу достичь

У меня есть объект хранилища, и я хочу заполнить одно из его свойств (которое является пустым массивом) экземплярами другого объекта.И я хочу, чтобы один из моих реагирующих компонентов автоматически обновлялся при изменении части упомянутого экземпляра массива.

В чем моя проблема

При выходе значения этого построенного объекта хранилища я могу видетьизменяется в консоли браузера, но он не обновляется автоматически в компоненте реагирования при изменении его значения.

Поэтому я хотел бы получить подсказки, примеры того, как реализовать подобное решение в целом.


Подробности

Мой проект

Я хочу создать хранилище MobX под названием Session , в котором будет храниться все, что нужно моему реагирующему веб-приложению.Это веб-приложение будет инструментом обработки документов, поэтому после создания новых или загрузки существующих документов я хочу добавить объект Document в Session (в массив объектов с именем documents ).Еще некоторые детали: Документ состоит из одного или нескольких разделов .Поэтому, используя редактор WYSIWYG, я добавляю его содержимое в данный раздел каждый раз, когда он меняется.

Проблема

Я могу добавить новый Документ в Сессию, я также могу обновить раздел (я могу выйти из значения раздела в консоли), но используя ссылку Session на этот документ и раздел в реагирующем компоненте, он не обновляет свое состояние, когдазначение раздела изменено.Насколько я понимаю, в моем примере ссылка на Document не изменяется при изменении значения раздела, и, следовательно, он не запускает MobX для реакции.

Что я нашел до сих пор

Я начал копаться в глубокой темной паутине и нашел эту статью.Поэтому я начал волноваться, так как asStructure (или asMap ), казалось, решил эту проблему, но похоже, что asStructure в MobX устарела.Затем я нашел этот поток проблема , где упоминается вещь под названием observable.structurallyCompare .Но опять же я ничего не нашел об этом в документации MobX, поэтому я озадачен тем, как это реализовать.

Так что я застрял снова и понятия не имею, как решить эту проблему.

Отрывки кода из моего проекта

Вот как я ссылаюсь на упомянутое значение сеанса в главном компоненте реакции:

import userSession from '../client/Session';
import {observer} from 'mobx-react';

@observer class App extends React.Component {
...

render() {

  return (
    ...
    <div>{JSON.stringify(userSession.documents[0].content.sections)}</div>

  ...

Вот так я обновляю раздел в компоненте редактора реакции:

import userSession from '../../client/Session';
...

handleChange(value,arg2,arg3,arg4) {
  this.setState({ content: value, delta: arg4.getHTML()});
  userSession.documents[0].updateSectionContent(this.props.id, this.state.delta);
  }
}

...

Session.js выдержка:

class Session {
  constructor(){
    extendObservable(this, {
      user: {
      },
      layout: {
      },
      documents: []
    })

    //current hack to add an empty Document to Session
    this.documents.push(new Document());
  }

  //yadayadayada...

  @action addNewSection() {
    userSession.documents[0].content.sections.push({
            type: "editor",
            id: userSession.documents[0].getNextSectionID(),
            editable: true,
            content: "",
            placeholder: "type here to add new section..."
    });
  }
}

var userSession = window.userSession = new Session();
export default userSession;

Document.js

import {extendObservable, computed, action} from "mobx";
import userSession from "./Session";

class Document {
  constructor(doc = null) {
    if (doc == null) {
      console.log("doc - no init value provided");
      extendObservable(this,{
        labels: {
          title: "title",
          description: "description",
          owners: ["guest"]
        },
        content: {
          sections: [
            {
              type: "editor",
              id: "sec1",
              editable: true,
              placeholder: "this is where the magic happens"
            },
          ]
        }
      })

    } else {
      console.log("doc - init values provided: ");
      extendObservable(this,{
        labels: doc.labels,
        content: doc.content
      });
    }
  }

  getNextSectionID(){
    return `sec${this.content.sections.length}`;
  }

  @action updateSectionContent(sectionID, delta) {
    console.log("doc - looking for section " + sectionID + " to update with this: " + delta);
    let index = this.content.sections.findIndex(
      section => section.id === sectionID
    );
    userSession.documents[0].content.sections[index].content = delta;

  }
}

export default Document;

Ps .: в настоящий момент я не помню, почему я сделал Document свойства наблюдаемыми, но по какой-то причине это было необходимо.

1 Ответ

0 голосов
/ 13 июня 2018

К сожалению, вы реализуете mobx с React неверным способом.Чтобы сделать его более понятным, я предлагаю вам взглянуть на реализацию HOC observer, которую обеспечивает mobx-react.

По сути, этот HOC заключается в том, чтобы обернуть ваш компонент внутри другого компонента React, который реализует shouldComponentUpdate, который проверяет, когда подпирает , указанный в функции render, и вызывает повторную команду.визуализации.Чтобы компонент React реагировал на изменения в хранилище mobx, вам необходимо передать ему данные хранилища как props, либо традиционным способом React, либо через inject HOC, предоставляемый mobx-react.

Проблема, когда ваш код не реагирует на изменения в хранилище, заключается в том, что вы импортируете хранилище и используете их непосредственно внутри компонента, mobx-react не может обнаружить изменение таким образом.

Вместо этого, чтобы сделать его реактивнымИмпортируя его и используя его непосредственно в App компоненте, вы можете передать хранилище как опору следующим образом:

@observer 
class App extends React.Component {
...

   render() {

     return (
     ...
       <div>{this.props.sections}</div>

     ...);
    }
}

Затем передать хранилище на App, когда оно будет использовано:

<App sections={userSession.documents[0].content.sections} />

Вы также можете посмотреть, как использовать inject здесь: https://github.com/mobxjs/mobx-react.

Просто предложение: перед тем, как прыгнуть прямо на какую-то best pattern, попробуйте придерживаться базового,Стандартным способом, которым автор библиотеки рекомендует и понимает, как он работает в первую очередь, вы можете рассмотреть другой вариант после того, как получите основную идею.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...