我有 public 和私有部分的react/redux/react-router
个应用程序。
登录和注册表单显示为模式对话框,没有自己的路由。
所需流程: 用户点击链接 - > 模式对话框显示在当前页面 - > 上,以便成功授权转换为链接页面,否则将用户留在当前页面。
如果当前没有页面显示索引页面并继续流程
我试图使用onEnter钩子将其归档,但据我所知,在执行钩子之前会发生转换。如果我尝试使用history.goBack()
它会导致页面重新呈现并且看起来很讨厌。
如果没有不必要的重定向和额外的渲染调用,有没有办法解决这个问题?
答案 0 :(得分:1)
好的 - 我想我想出了一种处理这个问题的方法,涵盖了所有的案例。它确实需要您通过某种方式从几乎任何组件访问应用程序状态。我正在使用Redux。这也假设登录,注册等没有路由。
我所做的是创建两个“包装”组件。第一个包装任何不安全的路由并将位置存储到状态值,以便我们始终引用最后一个不安全的路由......
import { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { setRoute } from './redux/client/ducks/auth';
function mapDispatchToProps(dispatch) {
return {
setRoute: bindActionCreators(setRoute, dispatch)
};
}
@connect(null, mapDispatchToProps)
export default class InsecureWrapper extends Component {
componentDidMount() {
const { location, setRoute } = this.props;
setRoute(location.pathname);
}
render() {
return (
<div>
{this.props.children}
</div>
)
}
}
另一个包装所有安全路线。它显示登录对话框(也可以在登录和注册之间来回切换等),并防止显示内容,除非登录到应用程序...
import { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as authActions from './redux/client/ducks/auth';
function mapStateToProps(state) {
return {
auth: state.auth
};
}
function mapDispatchToProps(dispatch) {
return {
authActions: bindActionCreators(authActions, dispatch)
};
}
@connect(
mapStateToProps,
mapDispatchToProps
)
export default class SecureWrapper extends Component {
componentDidMount() {
const { auth, authActions } = this.props;
//see if user and if not prompt for login
if(!auth.loggedIn) {
authActions.openLogin();
}
}
//close any open dialogs in case the user hit browser back or whatever
componentWillUnmount() {
const { authActions } = this.props;
authActions.resetAuthDialogs();
}
render() {
const { auth, children } = this.props;
return (
<div className="container">
{auth.loggedIn &&
{children} ||
<span>YOU MUST BE LOGGED IN TO VIEW THIS AREA!</span>
}
</div>
);
}
}
然后在路线中,根据需要将它们包装在包装中......
import App from './containers/App';
import Dashboard from './containers/Dashboard';
import Secure from './containers/Secure';
import AuthWrapper from './common/client/components/AuthWrapper';
import InsecureWrapper from './common/client/components/InsecureWrapper';
export default [
{path: '/', component: App, //common header or whatever can go here
childRoutes: [
{component: InsecureWrapper,
childRoutes: [ //<- ***INSECURE ROUTES ARE CHILDREN HERE***
{path: 'dashboard', component: Dashboard}
]
},
{component: SecureWrapper,
//***SECURE ROUTES ARE CHILDREN HERE***
childRoutes: [
{path: 'secure', component:Secure}
]
}
]}
]
最后但并非最不重要......在对话框中,您需要通过将位置推送(或替换)到保存的状态值来处理取消。当然,成功登录后,请关闭它们......
import { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as authActions from './redux/client/ducks/auth';
import LoginDialog from './common/client/components/dialogs/LoginDialog';
import RegisterDialog from './common/client/components/dialogs/RegisterDialog';
// this could also be replacePath if you wanted to overwrite the history
import { pushPath } from 'redux-simple-router';
function mapStateToProps(state) {
return {
auth: state.auth
};
}
function mapDispatchToProps(dispatch) {
return {
authActions: bindActionCreators(authActions, dispatch),
pushPath: bindActionCreators(pushPath, dispatch),
};
}
@connect(
mapStateToProps,
mapDispatchToProps
)
export default class AuthContainer extends Component {
_handleLoginCancel = (e) => {
const { auth, authActions, pushPath } = this.props;
pushPath(auth.prevRoute); // from our saved state value
authActions.closeLogin();
};
_handleLoginSubmit = (e) => {
const { authActions } = this.props;
// do whatever you need to login here
authActions.closeLogin();
};
render() {
const { auth } = this.props;
return (
<div>
<LoginDialog
open={auth.showLogin}
handleCancel={this._handleLoginCancel}
handleSubmit={this._handleLoginSubmit}
submitLabel="Login"
/>
...
</div>
)
}
}
我显然正在使用ES6,Babel和webpack ......但是原则应该在没有它们的情况下应用,因为不应该使用Redux(您可以将prev路由存储在本地存储中等等)。此外,为了简洁起见,我遗漏了一些传递道具的中间组件。
其中一些可能是功能组件,但我将它们留满了以显示更多细节。通过抽象其中一些内容也有一些改进的余地,但我再次将其留下来以显示更多细节。希望这有帮助!