[英]make a private route to async route in react router v4
我正在使用React Router v4在我的应用程序中进行路由。 组件,sagas和reducer异步加载。 在这种情况下,我现在如何实现私有路由和公共路由?
这是路由和加载的代码
/**
* A wrapper component that will lazily render a component after it has been loaded.
*/
class Bundle extends Component {
static contextTypes = {
store: React.PropTypes.object
};
state = {
// short for "module" but that's a keyword in js, so "mod"
mod: null
};
componentWillMount() {
this.load(this.props);
}
/* istanbul ignore next */
componentWillReceiveProps(nextProps) {
if (nextProps.load !== this.props.load) {
this.load(nextProps);
}
}
load(props) {
this.setState({
mod: null
});
props.load(this.context.store, mod => {
this.setState({
// handle both es imports and cjs
mod: mod.default ? mod.default : mod
});
});
}
render() {
// eslint-disable-next-line no-unused-vars
const { load, ...otherProps } = this.props;
return this.state.mod && <this.state.mod {...otherProps} />;
}
}
const AsyncRoute = ({ load, ...others }) => (
<Route {...others} render={props => <Bundle load={load} {...props} />} />
);
AsyncRoute.propTypes = {
computedMatch: React.PropTypes.object,
path: React.PropTypes.string,
load: React.PropTypes.func
};
export default AsyncRoute;
// how can i make private route with different layout not a children of App
function Routes({ location }) {
return (
<Switch location={location}>
<AsyncRoute exact path="/" load={loadHomePage} />
<AsyncRoute exact path="/signup" load={loadSignupPage} />
<AsyncRoute path="" load={loadNotFoundPage} />
</Switch>
);
}
export default (store, cb) => {
const { injectReducer, injectSagas } = getAsyncInjectors(store);
const importModules = Promise.all([
import("./reducer"),
import("./sagas"),
import("./index")
]);
importModules.then(([reducer, sagas, component]) => {
injectReducer("signup", reducer.default);
injectSagas(sagas.default);
cb(component);
});
importModules.catch(errorLoading);
};
const render = messages => {
ReactDOM.render(
<Provider store={store}>
<ConnectedRouter history={history}>
<App />
</ConnectedRouter>
</Provider>,
document.getElementById("app")
);
};
假设您已使用react-router-redux
将历史记录与redux存储区同步,则可以在主块中创建一个传奇,以从react-router-redux
获取最新的LOCATION_CHANGE
操作类型并刷新身份验证(将其存储在auth
reducer中) )调用一些API。
要区分私有组件和公共组件,您可以修改Bundle
,使其阻止异步加载私有块,直到auth
状态有效为止。
这是一些代码草图
传奇/ auth.js
import { LOCATION_CHANGE } from 'react-router-redux'
function *checkAuth() {
yield put(authenticateStart())
// Assuming using some token authentication
const token = yield select(state => state.auth.token)
const result = yield call(Api.refreshAuth, token)
if (result.isAuthenticated) {
yield put(authenticateSuccess(result.user)
} else {
// Need auth
yield put(authenticateError())
}
}
// Put this saga on main bundle
function *authSaga() {
yield* takeLatest(LOCATION_CHANGE, checkAuth)
}
bundle.js
class Bundle extends Component {
static contextTypes = {
store: React.PropTypes.object
};
state = {
// short for "module" but that's a keyword in js, so "mod"
mod: null
};
componentWillMount() {
if (this.props.isProtected && !this.props.isAuthenticated)
return
this.load(this.props);
}
/* istanbul ignore next */
componentWillReceiveProps(nextProps) {
// Modify similar to above
}
load(props) {
this.setState({
mod: null
});
props.load(this.context.store, mod => {
this.setState({
// handle both es imports and cjs
mod: mod.default ? mod.default : mod
});
});
}
render() {
// eslint-disable-next-line no-unused-vars
const { load, ...otherProps } = this.props;
return this.state.mod && <this.state.mod {...otherProps} />;
}
}
export default connect(state => ({ isAuthenticated: state.auth.isAuthenticated }))(Bundle)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.