1

与所有事情反应一样,我正在尝试做一些简单的事情,我猜我错过了一些明显的配置,我想做的就是使用一个 redux 应用程序并实现 mobx。

我的问题是我试图去路线 /user/12345

正在调用商店 - 我正在从 API 获取数据,但我得到了一些异常,第一个是来自 mobx

An uncaught exception occurred while calculation your computed value, autorun or tranformer. Or inside the render().... In 'User#.render()'

然后正如预期的那样,由于尚未加载商店,因此演示者中的空值正在爆炸

 Uncaught TypeError: Cannot read property 'name' of null

然后在商店本身,因为返回的 api/promise 我的用户被设置了一个 mobx 异常

Uncaught(in promise) Error: [mobx] Invariant failed: It is not allowed to create or change state outside an `action`

我已经将@action 添加到调用 api 的 store 函数中,所以我不确定我搞砸了什么 - 在我泡泡糖和大杂烩修复之前,我宁愿有一些反馈如何正确地做到这一点。谢谢。

用户商店.js

import userApi from '../api/userApi';
import {action, observable} from 'mobx';

class UserStore{
   @observable User = null;

   @action getUser(userId){
      userApi.getUser(userId).then((data) => {
         this.User = data;
      });
   }
}

const userStore = new UserStore();
export default userStore;
export{UserStore};

index.js

import {Router, browserHistory} from 'react-router';
import {useStrict} from 'mobx';
import routes from './routes-mob';

useStrict(true);
ReactDOM.render(
    <Router history={browserHistory} routes={routes}></Router>,
    document.getElementById('app')
);

路线-mob.js

import React from 'react';
import {Route,IndexRoute} from 'react-router';
import App from './components/MobApp';
import UserDetail from './components/userdetail';

export default(
    <Route name="root" path="/" component={App}>
       <Route name="user" path="user/:id" component={UserDetail} />
    </Route>
);

MobApp.js

import React,{ Component } from 'react';
import UserStore from '../mob-stores/UserStore';

export default class App extends Component{
   static contextTypes = {
      router: React.PropTypes.object.isRequired
   };

   static childContextTypes = {
      store: React.PropTypes.object
   };

   getChildContext(){
      return {
         store: {
            user: UserStore
         }
      }
   }

   render(){
      return this.props.children;
   }

}

.component/userdetail/index.js(容器?)

import React, {Component} from 'react';
import userStore from '../../mob-stores/UserStore';
import User from './presenter';

class UserContainer extends Component{
   static childContextTypes = {
       store: React.PropTypes.object
   };

   getChildContext(){
      return {store: {user: userStore}}
   }

   componentWillMount(){
      if(this.props.params.id){
         userStore.getUser(this.props.params.id);
      }
   }

   render(){
      return(<User />)
   }
}

export default UserContainer;

.component/userdetail/presenter.js

import React, {Component} from 'react';
import {observer} from 'mobx-react';

@observer
class User extends Component{
   static contextTypes = {
      store: React.PropTypes.object.isRequired
   }

   render(){
      const {user} = this.context.store;
      return(
          <div>{user.User.name}</div>
      )
   }
}

如果它有点混乱,请原谅我从各种博客文章以及文档和堆栈溢出问题中拼凑出的如何实现 mobx。我很难找到一个不仅仅是标准 todoapp 的简单示例

更新

基本上,修复是以下@mweststrate 答案的组合,将操作添加到承诺响应中

@action getUser(userId){
  userApi.getUser(userId).then(action("optional name", (data) => {
     // not in action
     this.User = data;
  }));

}

并包括在演示者中检查我们实际上有一些东西要显示

<div>{this.context.store.user.User ? this.context.store.user.User.name : 'nada' }</div>
4

1 回答 1

4

请注意,以下代码不受操作保护:

   @action getUser(userId){
      userApi.getUser(userId).then((data) => {
         // not in action
         this.User = data;
      });
   }

only 修饰当前action函数,但回调是另一个函数,所以改为使用:

   @action getUser(userId){
      userApi.getUser(userId).then(action("optional name", (data) => {
         // not in action
         this.User = data;
      }));
   }
于 2016-08-01T12:24:58.337 回答