你如何以反应方式从 mobx observable 中获取项目?
How do you get an item from a mobx observable in a reactive manner?
让我们假设有一个单身人士 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 助手不在视图中。
请问有更好的方法吗?
一解
一种方法是使用 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 知道,你的组件需要监听你的 observable 的变化,你必须 "do" 这个 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 方法中获取您的待办事项,并且您的组件监听 isLoading 属性的变化,所以当 isLoading 变化时您的组件将被调用。
使用此解决方案,您的组件会在每次 isLoading 更改时重新呈现。
如您所见,访问可观察对象的方式会有所不同。这取决于您希望组件在什么情况下重新呈现。
让我们假设有一个单身人士 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 助手不在视图中。
请问有更好的方法吗?
一解
一种方法是使用 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 知道,你的组件需要监听你的 observable 的变化,你必须 "do" 这个 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 方法中获取您的待办事项,并且您的组件监听 isLoading 属性的变化,所以当 isLoading 变化时您的组件将被调用。
使用此解决方案,您的组件会在每次 isLoading 更改时重新呈现。
如您所见,访问可观察对象的方式会有所不同。这取决于您希望组件在什么情况下重新呈现。