你如何以被动的方式从一个mobx中观察到一个物品?

时间:2018-04-27 22:17:12

标签: reactjs mobx

让我们假设单身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的todo详细信息视图,例如/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 :(得分:3)

一个解决方案

一种方法是使用React的setState方法。

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

第二个解决方案

另一种方法是访问(取消引用)组件中的待办事项。就这样,当todos发生变化时,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知道你的组件需要监听你的observable的变化,你必须用这个observable“做”一些东西。 要么访问observable的prop,要么就像在这种情况下调用方法(这里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>
    );
   }
}

因为组件现在在render方法中获取你的todo,并且你的组件在isLoading prop上侦听更改,所以当isLoading发生更改时,将调用你的组件。

使用此解决方案,您的组件每次都会重新发送isLoading更改。

如您所见,您访问可观察对象的方式会有所不同。这取决于您希望组件重新呈现的条件。