Vor einer Woche haben wir begonnen, ein neues Projekt mit mit reagieren und mobx, und ich vor dem gleichen Problem wie Sie. Nachdem ich mich umgesehen habe, fand ich den besten Weg, den Kontext von von react zu verwenden. Hier ist, wie:
Shop: 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();
Hinweis: wir Singleton verwenden, um sicherzustellen, dass es eine Instanz nur, weil der Speicher verwendet werden kann, außerhalb reagieren Komponenten, zB. routes.js
Die Routen: 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>
);
Die Hauptkomponente: 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;
}
}
Und schließlich eine Komponente den Laden mit: 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>
);
}
}
Sie können neue Geschäfte erklären und fügen Sie sie inhinzuvon App.js
, und wann immer Sie einen bestimmten Speicher benötigen, deklarieren Sie einfach die store
Abhängigkeit in contextTypes
der Komponente, und erhalten Sie es von this.context
.
Ich bemerkte, dass es nicht erforderlich ist, ein beobachtbaren als Stütze passiert, nur durch die @observer
Dekorateur hat und jeden beobachtbaren Wert in Ihrer Komponente verwenden, mobx
und mobx-react
ihre Magie tun.
Übrigens tut Redux <Provider store={myStore}><App /></Provider>
das Gleiche wie in App.js
erläutert. https://egghead.io/lessons/javascript-redux-passing-the-store-down-implicitly-via-context
Referenz:
Reagiert das Mobx-Typoskript-Beispiel, wie man sie explizit weitergibt? – dagatsoin
Vielleicht habe ich eine falsche Vorstellung von der Auswirkung auf die Leistung, um einen ganzen Laden in einer oberen Komponente zu übergeben. Vielleicht ist die Antwort auf meine Frage eine andere Frage: Ist es eine gute Methode, einen ganzen Speicher an eine Komponente zu übergeben? Und die offensichtliche Antwort ist ja. Ich mache das schon mit Redux-Provider ... Bestätigst du? – dagatsoin
Ja, ich bestätige. Ein Geschäft ist nur eine Referenz. Sollte sehr effizient sein, um herumzugehen :) Es stellt auch sicher, dass Sie alle "Modell" -Api zur Verfügung haben, die Sie möglicherweise in Ihrer Komponente benötigen. – mweststrate