如何使用 mobx 将状态连接到道具.js @observer当使用 ES6 类时
How to connect state to props with mobx.js @observer when use ES6 class?
让我们在带有 React 和 React Router 的应用程序中学习这样的类。
@observer class Module1 extends React.Component {
constructor (props) {
super(props);
//...
}
componentWillMount(){
//...
}
method(){
//...
}
otherMethod(){
//...
}
render() {
return (
<ChildComp bars={this.props.bars}/>}
);
}
}
让我们采取这样的状态
state = observable({
module1:{
bars:{
//...
}
},
module2:{
foos:{
//...
}
}
})
模块 1 组件的加载方式如下:
//index.js
render(
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path='/map' component={Module1} >
<Route path="/entity/:id" component={SubModule}/>
</Route>
<Route path='/map' component={Module2} >
</Route>
</Router>,
document.getElementById('render-target')
);
如何将道具module1.bars
传递给模块 1 组件?在 redux 中,我会使用 <provider>
和 redux-connect
但我在 Mobx.js 中对此有点迷茫。
一周前,我们用 react 和 mobx 开始了一个新项目,我遇到了和你一样的问题。环顾四周后,我发现最好的方法是使用 react 的上下文。方法如下:
商店:stores/Auth.js
import { get, post } from 'axios';
import { observable, computed } from 'mobx';
import jwt from 'jsonwebtoken';
import singleton from 'singleton';
import Storage from '../services/Storage';
class Auth extends singleton {
@observable user = null;
@computed get isLoggedIn() {
return !!this.user;
}
constructor() {
super();
const token = Storage.get('token');
if (token) {
this.user = jwt.verify(token, JWT_SECRET);
}
}
login(username, password) {
return post('/api/auth/login', {
username, password
})
.then((res) => {
this.user = res.data.user;
Storage.set('token', res.data.token);
return res;
});
}
logout() {
Storage.remove('token');
return get('/api/auth/logout');
}
}
export default Auth.get();
注意:我们使用单例来确保它只是一个实例,因为该存储可以在 react 组件之外使用,例如。 routes.js
路线:routes.js
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import App from './App';
import Login from './Login/Login';
import Admin from './Admin/Admin';
import Dashboard from './Admin/views/Dashboard';
import Auth from './stores/Auth'; // note: we can use the same store here..
function authRequired(nextState, replace) {
if (!Auth.isLoggedIn) {
replace('/login');
}
}
export default (
<Route name="root" path="/" component={App}>
<Route name="login" path="login" component={Login} />
<Route name="admin" path="admin" onEnter={authRequired} component={Admin}>
<IndexRoute name="dashboard" component={Dashboard} />
</Route>
</Route>
);
主要成分:App.js
// App.js
import React, { Component } from 'react';
import Auth from './stores/Auth';
export default class App extends Component {
static contextTypes = {
router: React.PropTypes.object.isRequired
};
static childContextTypes = {
store: React.PropTypes.object
};
getChildContext() {
/**
* Register stores to be passed down to components
*/
return {
store: {
auth: Auth
}
};
}
componentWillMount() {
if (!Auth.isLoggedIn) {
this.context.router.push('/login');
}
}
render() {
return this.props.children;
}
}
最后,使用存储的组件:Login.js
import React, { Component } from 'react';
import { observer } from 'mobx-react';
@observer
export default class Login extends Component {
static contextTypes = {
router: React.PropTypes.object.isRequired,
store: React.PropTypes.object.isRequired
};
onSubmit(e) {
const { auth } = this.context.store; // this is our 'Auth' store, same observable instance used by the `routes.js`
auth.login(this.refs.username.value, this.refs.password.value)
.then(() => {
if (auth.isLoggedIn) this.context.router.push('/admin');
})
.catch((err) => {
console.log(err);
});
e.preventDefault();
}
render() {
return (
<div className="login__form">
<h2>Login</h2>
<form onSubmit={this.onSubmit.bind(this)}>
<input type="text" ref="username" name="username" placeholder="Username" />
<input type="password" ref="password" name="password" placeholder="Password" />
<button type="submit">Login</button>
</form>
</div>
);
}
}
你可以声明新的存储并将它们添加到App.js
getChildContext
,每当你需要某个存储时,只需在组件的contextTypes
中声明store
依赖项,并从this.context
获取它。
我注意到不需要将可观察量作为道具传递,只需拥有@observer
装饰器并在组件中使用任何可观察值,mobx
和mobx-react
发挥它们的魔力。
顺便说一下,redux 的<Provider store={myStore}><App /></Provider>
与 App.js
中所述的相同。 https://egghead.io/lessons/javascript-redux-passing-the-store-down-implicitly-via-context
参考:
- http://mobxjs.github.io/mobx/refguide/observer-component.html
- https://facebook.github.io/react/docs/context.html
mobx-react 提供了一个(实验性的 - 在撰写本文时)Provider
(组件)和inject
(高阶组件)来将属性传递给下面的组件层次结构。
从上面,您可以使用Provider
组件传递所有相关信息。在引擎盖下使用 React 上下文。
import { Provider } from 'mobx-react';
...
import oneStore from './stores/oneStore';
import anotherStore from './stores/anotherStore';
const stores = { oneStore, anotherStore };
ReactDOM.render(
<Provider { ...stores }>
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="/" component={SomeComponent} />
</Route>
</Router>
</Provider>,
document.getElementById('app')
);
在SomeComponent
中,您可以使用inject
HOC 检索传递的属性:
import { observer, inject } from 'mobx-react';
...
const SomeComponent = inject('oneStore', 'anotherStore')(observer(({ oneStore, anotherStore }) => {
return <div>{oneStore.someProp}{anotherStore.someOtherProp}</div>;
}))
export default SomeComponent;
[免责声明:我在 MobX React:React 中的简化状态管理中写过它,你可以看到一个使用 SoundCloud API 的最小样板应用程序。
首先,这里有一个简单的示例应用程序,它使用 MobX、React 和 react-router 进行路由: https://github.com/contacts-mvc/mobx-react-typescript
一般来说,我个人喜欢将所有相关商店作为显式道具显式传递给我的组件。但是你也可以使用像 Ryan 这样的包,通过 React 上下文机制将你的商店传递给你的组件,类似于 Redux connect(有关示例,请参阅此应用程序)。
在组件中拥有存储后,解析 ComponentWillMount 中的路由参数并相应地更新存储。
这基本上应该是全部:)但是,如果我有任何未回答的问题,请告诉我。
看看 react-tunnel。它为您提供了一个Provider
组件和inject
装饰器(工作方式类似于 redux 中的connect
)。
- 可以't让我的if语句处理js中的html表单输入
- 使用agility.js进行页面布局和合成
- 使用Clipboard.js复制span文本
- 使用JS如何动态更改显示的html文件中的文本背景颜色
- 强制模板刷新ember.js
- 如何编写HTML输入的JS内联
- Angular JS IE9 Hashbang url rewriting
- 使用JS将数组转换为json对象
- Node.js v6.2.0类扩展不是函数错误
- 当js函数's已执行
- 要求未定义JS回调参数
- 在自定义mean.io包中使用angular-chart.js作为依赖项
- 无法在数据endVal中设置值=“”;{{ucount}}”;使用Angular JS的CountUp
- 如何从Java/scala调用js美化程序
- 如何更改<svg>标记为<img>用js标记
- ember.js所有值的observer
- 如何使用 mobx 将状态连接到道具.js @observer当使用 ES6 类时
- Ember.js中的Subscriber/Observer模式
- Prototype.js - Form.element.observer + Internet Explorer + S
- JS: prototype event-observer没有触发