Правильный способ создания нескольких магазинов с помощью mobx и добавления его в компонент - ReactJs - PullRequest
0 голосов
/ 28 января 2019

Как предлагается здесь в документации Mobx Я создал несколько хранилищ следующим образом:

class bankAccountStore {
  constructor(rootStore){
    this.rootStore = rootStore;
  }
...

class authStore {
  constructor(rootStore){
    this.rootStore = rootStore;
  }
...

И, наконец, , создав корневое хранилище в следующемманера.Также Я предпочитаю создавать дочерние магазины в конструкторе магазина мастера.Более того, я обнаружил, что иногда моему дочернему хранилищу приходится наблюдать некоторые данные из родительского хранилища, поэтому я передаю их в дочерние конструкторы

class RootStore {
  constructor() {
    this.bankAccountStore = new bankAccountStore(this);
    this.authStore = new authStore(this);
  }
}

Предоставление приложению следующим образом:

<Provider rootStore={new RootStore()}>
  <App />
</Provider>

И внедрение в компонент следующим образом:

@inject('rootStore') 
@observer
class User extends React.Component{
  constructor(props) {
    super(props);
    //Accessing the individual store with the help of root store
    this.authStore = this.props.rootStore.authStore;
  }
}

Это правильный и эффективный способ внедрить корневое хранилище каждый раз в компонентдаже если ему нужна часть корневого хранилища?Если не как внедрить auth Store в пользовательский компонент?

EDIT: я сделал ответ, завершив обсуждение github.Ссылка на обсуждение приведена в ответе

Ответы [ 2 ]

0 голосов
/ 28 марта 2019

Этот ответ может быть самоуверенным, но может косвенно помочь сообществу.После долгих исследований я увидел следующие подходы, используемые на практике многими.Общие методы Иметь корневое хранилище, которое может выступать в качестве канала связи между магазинами.

Вопрос 1. Как организовать магазины и внедрить их в компонент?

Подход 1:

App.js

// Root Store Declaration
class RootStore {
    constructor() {
      this.userStore = new UserStore(this);
      this.authStore = new AuthStore(this);
    }
}    
const rootStore = new RootStore()

// Provide the store to the children
<Provider 
    rootStore={rootStore}
    userStore={rootStore.userStore}
    authStore={rootStore.authStore}
>
  <App />
</Provider>

Component.js

// Injecting into the component and using it as shown below
@inject('authStore', 'userStore')
@observer
class User extends React.Component {
    // only this.props.userStore.userVariable
}

Подход 2:

App.js

class RootStore {
    constructor() {
      this.userStore = new UserStore(this);
      this.authStore = new AuthStore(this);
    }
} 
const rootStore = new RootStore()

<Provider rootStore={rootStore}>
  <App />
</Provider>

Component.js

// Injecting into the component and using it as shown below
@inject(stores => ({
    userStore: stores.userStore,
    authStore: stores.authStore,
    })
)
@observer
class User extends React.Component {
    // no this.props.rootStore.userStore,userVariable here, 
    // only this.props.userStore.userVariable
}

Подход 1 и Подход 2 не имеют никакой разницы, кроме синтаксической разницы.Хорошо!это часть впрыска!

Вопрос 2: Как установить связь между магазинами?(Постарайтесь избежать этого)

Теперь я знаю, что хороший дизайн сохраняет магазины независимыми и менее связанными.Но как-то рассмотрим сценарий, в котором я хочу, чтобы переменная в UserStore изменилась, если изменилась определенная переменная в AuthStore.Используйте Computed.Этот подход является общим для обоих вышеуказанных подходов

AuthStore.js

export class AuthStore {    
    constructor(rootStore) {
        this.rootStore = rootStore
        @computed get dependentVariable() {
          return this.rootStore.userStore.changeableUserVariable;                                      
        }
    }
}

Надеюсь, это поможет сообществу.Для более подробного обсуждения вы можете обратиться к проблеме , поднятой мной на Github

0 голосов
/ 28 января 2019

Я бы порекомендовал вам иметь несколько магазинов, чтобы избежать цепочки магазинов.Как мы делаем в нашем приложении:

class RootStore {
    @observable somePropUsedInOtherStores = 'hello';
}

class AuthStore {
    @observeble user = 'Viktor' ; 

    constructor(rootStore) {
        this.rootStore = rootStore;
    }

    // this will reevaluate based on this.rootStore.somePropUsedInOtherStores cahnge
    @computed get greeting() {
        return `${this.rootStore.somePropUsedInOtherStores} ${this.user}`
    }
}

const rootStore = new RootStore();

const stores = {
    rootStore,
    bankAccountStore: new BankAccountStore(rootStore),
    authStore = new AuthStore(rootStore) 
}

<Provider {...stores}>
  <App />
</Provider>

Таким образом, вы можете получить доступ именно к нужному магазину, так как в основном один магазин покрывает один экземпляр домена.Тем не менее, оба под-магазина могут общаться на rootStore.Установите его свойства или вызовите методы для него.

Если вам не нужна связь между магазинами - вам может вообще не понадобиться rootStore.Удалите его и не переходите в другие магазины.Просто держите 2 родных магазина

Отвечая на ваш вопрос о введении не целого магазина, вы можете извлечь выгоду из mapperFunction (например, mapStateToProps в редуксе) документов здесь

@inject(stores => ({
        someProp: stores.rootStore.someProp
    })
)
@observer
class User extends React.Component {
// no props.rootStore here, only props.someProp

}
...