由于您正在转向前端路由,我建议您集成 react-router(我更喜欢 v3.0.4 而不是 v4.x)仅用于处理前端路由和 express(或任何您想要的using) 仅用于处理后端 API 请求。
以下示例仅用于路由演示目的,不应按原样使用。
首先,在客户端的package.json中设置代理(这样做的主要好处是避免使用CORS):
"proxy": {
"/api/*": {
"target": "http://localhost:8080"
}
}
我的客户 routes 将被设置为使 App 始终保持挂载并充当 children 路由的传递:
client/src/routes/index.js
import React from 'react';
import { Route } from 'react-router';
import App from '../components/App';
import Dashboard from '../components/Dashboard';
import NotFound from '../components/NotFound';
export default (
<Route path="/" component={App}>
<Route path="dashboard" component={Dashboard} />
<Route path="*" component={NotFound} />
</Route>
);
在我的App.js 中,我可以使用isAuthenticated 状态检查:
client/src/components/App.js
import React, { Component, Fragment } from 'react';
import { browserHistory } from 'react-router';
import LoginForm from './LoginForm'
export default class App extends Component {
state = { isAuthenticated: false };
componentDidMount = () => !this.state.isAuthenticated && browserHistory.push('/')
componentDidUpdate = (prevProps, prevState) => !this.state.isAuthenticated && browserHistory.push('/')
authenticated = () => this.setState({ isAuthenticated: true }, () => browserHistory.push('/dashboard'))
render = () => (
!this.state.isAuthenticated
? <LoginForm authenticated={this.authenticated} />
: <Fragment>
{this.props.children}
</Fragment>
)
}
然后,在LoginForm 组件中,我可以在AJAX 请求成功时通过this.props.authenticated 将isAuthenticated 设置为true,然后重定向到dashboard:
client/src/components/LoginForm.js
import React, {Component} from 'react';
import axios from 'axios';
export default class LoginForm extends Component {
state = {
login: "",
password: ""
}
handleChange = e => this.setState({ [e.target.name]: e.target.value })
handleSubmit = e => {
e.preventDefault();
const { login, password } = this.state;
if (!login || !password ) return;
axios.post('/api/login', { login, password })
.then(() => this.props.authenticated())
.catch(err => console.error(err.toString()))
}
render = () => (
<form onSubmit={this.handleSubmit} className="some-class">
<input
name="login"
type="text"
value={this.state.login}
placeholder="Username"
onChange={this.handleChange}
/>
<input
name="password"
type="password"
value={this.state.password}
placeholder="Password"
onChange={this.handleChange}
/>
<button type="submit" className="some-class">
Log In
</button>
</form>
)
}
那么快递服务器routes 会寻找POST 请求:
server/routes/auth.js
const { login } = require('../controllers/auth.js');
app.post('/login', login);
然后,我可以在我的 express 控制器中通过 passport 对用户进行身份验证(如果用户未能通过身份验证,那么它将被捕获在 handleSubmit 内的 AJAX .catch() 中):
服务器/控制器/auth.js
exports.login = (req, res, done) => passport.authenticate('local-login', (err, user) => {
if (err || !user) { res.status(404).json({ err: "Authentication failed." }); done(); }
res.status(201).send(null);
})(req, res, done)