react-router-config-guard
Version:
Static route config and guard for React Router, base on react-router-config
174 lines (147 loc) • 6.09 kB
JSX
import React from "react";
import { Redirect, Route } from "react-router";
import { useState, useContext } from "react";
import { memo, useCallback, useEffect } from "react"
import { __RouterContext as RouterContext } from 'react-router';
import { FromRouteContext } from './Contexts.jsx';
// const from = createContext(FromRouteContext);
// const to = createContext(RouterContext);
// class RouterGuard2 extends React.PureComponent {
// hasRouteGuard
// guardToRedirect = false;
// isRedirect = false;
// redirectPath = "";
// constructor(props) {
// super(props);
// this.hasRouteGuard = !!this.props.routerBeforeEach;
// this.state = {
// routeGuardFinished: false,
// }
// }
// getTo() {
// return { ...to, meta: this.props.route.meta || {}, route: this.props.route }
// }
// componentDidMount() {
// if (!this.hasRouteGuard) {
// return;
// }
// this.props.routerBeforeEach(this.getTo(), from, (to) => {
// if (!to) {
// this.guardToRedirect = false;
// this.setState({
// routeGuardFinished: true
// })
// } else {
// if (typeof to === 'string') {
// this.redirectPath = to;
// this.isRedirect = false;
// this.guardToRedirect = true;
// this.setState({
// routeGuardFinished: true
// })
// } else if (typeof to === 'object' && (typeof to.path === 'string' || typeof to.name === 'string')) {
// this.redirectPath = to.path || to.name;
// this.isRedirect = to.replace || false;
// this.guardToRedirect = false;
// this.setState({
// routeGuardFinished: true
// })
// } else {
// console.log(`Your next format is incorrect, should be : next('/') or next({ path: '/' }) or next({ path: '/', replace: true})`);
// this.guardToRedirect = false;
// this.setState({
// routeGuardFinished: true
// })
// }
// }
// })
// }
// render() {
// var { routerAfterEach, route, history } = this.props
// if (!this.state.routeGuardFinished) {
// return null;
// }
// if (this.guardToRedirect && this.redirectPath) {
// routerAfterEach && routerAfterEach(this.getTo());
// if (this.isRedirect) {
// return <Redirect to={this.redirectPath} {...this.props} />
// } else {
// if (history) {
// history.push(this.redirectPath);
// return null;
// } else {
// return <Route to={this.redirectPath} {...this.props} />
// }
// }
// }
// routerAfterEach && routerAfterEach(this.getTo());
// return React.createElement(route.component, this.props);
// }
// }
const RouterGuard = memo(function (props) {
// console.log("init RouterGuard");
var { routerBeforeEach, routerAfterEach, route, history } = props
const from = useContext(FromRouteContext);
const to = useContext(RouterContext);
const getTo = useCallback(() => {
return { ...to, meta: route.meta || {}, route }
}, [to, route])
// const hasRouteGuard = !!routerBeforeEach;
const [routeGuardFinished, setRouteGuardFinished] = useState(false);
const [redirectPath, setRedirectPath] = useState("");
const [guardToRedirect, setGuardToRedirect] = useState(false);
const [isRedirect, setIsRedirect] = useState(false);
const hook = useCallback((to, from, next) => {
routerBeforeEach && routerBeforeEach(to, from, next);
}, [routerBeforeEach])
useEffect(() => {
if (!routerBeforeEach) {
setRouteGuardFinished(true);
setGuardToRedirect(false);
} else {
hook(getTo(), from, (to) => {
if (!to) {
setGuardToRedirect(false);
setRouteGuardFinished(true);
} else {
// next('/') or next({ path: '/' }) -> redirect
if (typeof to === 'string') {
setRedirectPath(to);
setIsRedirect(false);
setGuardToRedirect(true);
setRouteGuardFinished(true);
} else if (typeof to === 'object' && (typeof to.path === 'string' || typeof to.name === 'string')) {
setRedirectPath(to.path || to.name);
setIsRedirect(to.replace || false);
setGuardToRedirect(true);
setRouteGuardFinished(true);
} else {
console.log(`Your next format is incorrect, should be : next('/') or next({ path: '/' }) or next({ path: '/', replace: true})`);
setGuardToRedirect(false);
setRouteGuardFinished(true);
}
}
})
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [hook])
if (!routeGuardFinished) {
return null;
}
if (guardToRedirect && redirectPath) {
routerAfterEach && routerAfterEach(getTo());
if (isRedirect) {
return <Redirect to={redirectPath} {...props} />
} else {
if (history) {
history.push(redirectPath);
return null;
} else {
return <Route to={redirectPath} {...props} />
}
}
}
routerAfterEach && routerAfterEach(getTo());
return React.createElement(route.component, props);
})
export default RouterGuard;