Как вы получаете предмет из MOBX, наблюдаемый в реактивной манере? - PullRequest
0 голосов
/ 28 апреля 2018

Давайте предположим, что есть синглтон TodosStore, который выглядит примерно так:

class TodosStore {
    @observable isLoading;
    @observable todos;

    @action.bound fetchTodos() {
        this.isLoading = true;
        return api.getTodos().then(todos => this.todos = todos)
            .finally(()=>this.isLoading=false);
    }

    getTodoById(id) {
        return this.todos.find(todo => todo.id === id);
    }
}

Давайте также предположим один подробный просмотр задачи, который использует URL для состояния, например, /todos/123.

@observer class TodoDetail extends React.Component {
    constructor(props){
        TodosStore.fetchTodos().then(
            this.todo = TodosStore.getTodoById(props.subscriptionId);
        );
    }
    render(){
        return (
            <div>
                {TodosStore.isLoading ?
                    'Loading, please wait...' :
                    <h1>this.todo.text</h1>
                }
            </div>
        );
    }
}

Итак, this.todo, очевидно, не является реактивным, поэтому его установка не будет повторяться render().
Один из вариантов - создать @observable todo; в коде представления, но я бы предпочел не допускать помощников mobx к представлениям.

Есть ли лучший способ сделать это, пожалуйста?

1 Ответ

0 голосов
/ 28 апреля 2018

Одно решение

Одним из способов является использование метода React setState.

 constructor(props){
    TodosStore.fetchTodos().then({
        this.setState({ todo: TodosStore.getTodoById(props.subscriptionId) })
    });
}

Второй раствор

Другим способом будет доступ (разыменование) к задачам в вашем компоненте. Таким образом, mobx знает, что этот компонент должен обновляться при изменении задач.

class TodoStore {
 @observable todos = []; //initialize your todos as empty array
}

@observer class TodoDetail extends React.Component {
   constructor(props){
      TodosStore.fetchTodos();
   }

   render(){
    const todo = TodoStore.todos.find(todo => todo.id === this.props.subscriptionId);
    return (
        <div>
            {TodosStore.isLoading ?
                'Loading, please wait...' :
                <h1>todo.text</h1>
            }
        </div>
    );
   }
}

В этом случае при каждом изменении массива задач компонент будет пытаться найти задачу и выполнить повторное рендеринг.

Чтобы дать mobx понять, что ваши компоненты должны прислушиваться к изменениям вашей наблюдаемой, вы должны что-то «сделать» с этой наблюдаемой. Либо получить доступ к реквизиту наблюдаемого, либо, как в этом случае, вызвать метод (здесь todos.find())

И еще есть третье решение

class TodoStore {
 @observable todos = []; //initialize your todos as empty array
}

@observer class TodoDetail extends React.Component {
   constructor(props){
      TodosStore.fetchTodos();
   }

   render(){
    const todo = TodosStore.getTodoById(props.subscriptionId);
    return (
        <div>
            {TodosStore.isLoading ?
                'Loading, please wait...' :
                <h1>todo.text</h1>
            }
        </div>
    );
   }
}

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

При использовании этого решения ваш компонент перерисовывается каждый раз при загрузке изменений.

Как видите, способ доступа к наблюдаемому объекту имеет значение. Это зависит от того, при каких условиях вы хотите, чтобы ваш компонент перерисовался.

...