好的 - 我想我想出了一種處理這個問題的方法,它涵蓋了所有的角落案例。它確實需要你有一些方法可以從幾乎任何組件訪問應用程序狀態。我正在使用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,巴貝爾和的WebPack ......但原則應不應該使用Redux的申請沒有他們(你可以存儲prev在本地存儲路由或其他)。此外,爲了簡潔,我省略了一些通過道具的中間組件。
其中一些可能是功能組件,但我將它們留下來以顯示更多細節。通過對這些內容進行抽象還有一些改進的餘地,但是我再次將它留給冗餘以顯示更多細節。希望這可以幫助!
如果沒有先前的路由,我忘記了關於索引的部分,但如果前面的路由爲空/空,那只是推/替換中的一個IF。 –
雖然提供了相當不錯的流程來處理直接導航到私人頁面,但它並沒有幫助主要問題 - 在當前頁面上顯示模態窗口,而不是在目標頁面上顯示。 我正在尋找某種位置更改回調之前,但看起來像我只是需要延長鏈接標記 – ETK
是的我想到了和刪除onTransitionTo一樣多,還沒有找到更好的方式來處理它。這確實非常接近,因爲如果它沒有登錄,它就隱藏了目標頁面上的內容,除登錄之外唯一的'out'取消 - 這些路由返回到它們來自的頁面(或'home')。我有我的對話框能夠從任何頁面啓動,所以這很好用,只需要將它保存在路由中的一個地方。對不起,沒有什麼比你想要的更多幫助。 –