#reactjs #react-router
Вопрос:
Поэтому после того, как пользователь вошел в систему, getProfile()
вызывается, чтобы получить информацию об их профиле.
и по их роли пользователи будут переходить к user page
или admin page
.
Для этого я создал ProtectedRoute
компонент.
Но каждый user page
и admin page
не отображается, когда я использую этот компонент.
(отображается только белый экран.)
Я проверил getProfile()
, что компонент в ProtectedRoute хорошо получает результат.
но кажется <Layout {...props} />
, что это или <AdminLayout {...props} />
не отображается.
Вот коды.
protectedRoute.js : Отфильтруйте пользователей по их ролям и перейдите к соответствующей странице.
import React, {useEffect} from 'react';
import {BrowserRouter as Router, Switch, Route, Redirect} from 'react-router-dom';
import Layout from './layouts/layout';
import AdminLayout from './layouts/adminLayout';
import {useDispatch} from 'react-redux';
import {getProfile} from './data_actions/userInfo_action/userInfo_action';
import {unwrapResult} from '@reduxjs/toolkit';
import {useHistory} from 'react-router-dom';
export const ProtectedRoute = ({component: Component, admin = null, ...rest}) => {
const dispatch = useDispatch();
return (
<Route
{...rest}
path={rest.path}
render={(props) => {
dispatch(getProfile())
.then(unwrapResult)
.then((res) => {
if ((res.role === 'PRO' || res.role === 'CLIENT') amp;amp; !admin) {
<Layout {...props} />;
} else if (res.role === 'ADMIN' amp;amp; admin) {
<AdminLayout {...props} />;
}
})
.catch((err) => {
return (
<Redirect
to={{
pathname: '/',
state: {
from: props.location,
},
}}
/>
);
});
}}
/>
);
};
App.jsx : Где размещен компонент protectedRoute.
import React, {useContext, useEffect, useRef, useState} from 'react';
import Layout from './layouts/layout';
import AdminLayout from './layouts/adminLayout';
import './App.scss';
import {BrowserRouter as Router, Switch, Route, Redirect} from 'react-router-dom';
import LoginPage from '@/pages/user/sign/login';
import NotFound from './pages/notFound';
import {ProtectedRoute} from './protectedRoute';
function App() {
return (
<Router>
<Switch>
{/* login */}
<Route exact path={`/fn/sign/login`} render={(props) => <LoginPage {...props} />} />
<ProtectedRoute exact path={`${process.env.PUBLIC_URL}`} component={Layout} admin={false} />
<ProtectedRoute
exact
path={`${process.env.PUBLIC_URL}/admin`}
component={AdminLayout}
admin={true}
/>
<Route path="*" component={NotFound} />
</Switch>
</Router>
);
}
export default App;
layout.jsx : Layout Component that contains user’s router.
import React, {memo, useContext, useEffect} from 'react';
import PropTypes from 'prop-types';
import Drawer from '@material-ui/core/Drawer';
import Hidden from '@material-ui/core/Hidden';
import {makeStyles, useTheme} from '@material-ui/core/styles';
import SideBar from './sidebar';
import './layout.scss';
import Router from '../routes/router';
const useStyles = makeStyles((theme) => ({
root: {
display: 'flex',
},
toolbar: {
[theme.breakpoints.up(theme.breakpoints.values.md)]: {
display: 'none',
},
},
content: {
width: '100%',
flexGrow: 1,
},
}));
function Layout(props) {
const classes = useStyles();
return (
<div className={classes.root}>
<nav className={classes.drawer}>
<Hidden mdDown implementation="css">
<Drawer
className={classes.drawer}
classes={{
paper: classes.drawerPaper,
}}
variant="permanent"
open
>
<SideBar />
</Drawer>
</Hidden>
</nav>
<main className={classes.content}>
<div className={classes.toolbar} />
<Router {...props} />
</main>
</div>
);
}
Layout.propTypes = {
window: PropTypes.func,
};
export default memo(Layout);
router.js : страницы пользователя
import React, {useEffect} from 'react';
import {Switch, Route, Redirect} from 'react-router-dom';
import JobList from '@/pages/user/jobNotiBoard/jobList';
import JobDetail from '@/pages/user/jobNotiBoard/jobDetail';
import NotFound from '@/pages/notFound';
import {useDispatch, useSelector} from 'react-redux';
import {setNewCount2} from '@/data_actions/jobNoti_action/newDataCount_action';
function Router(props) {
const dispatch = useDispatch();
const newDataCount = useSelector((state) => state.newJobNotiPostCount);
useEffect(() => {
dispatch(setNewCount2());
}, []);
return (
<React.Fragment>
<Switch>
<Route
exact
path={`${process.env.PUBLIC_URL}/joblist`}
render={(props) => <JobList {...props} newDataCount={newDataCount?.count} />}
/>
<Route
path={`${process.env.PUBLIC_URL}/detail/:id/:site`}
render={(props) => <JobDetail {...props} />}
/>
<Route path="*" component={NotFound} />
</Switch>
</React.Fragment>
);
}
export default Router;
Ответ №1:
Рендеринг prop
в вашем ProtectedRoute
ничего не возвращает.
Вам придется изменить его на что-то вроде
export const ProtectedRoute = ({
component: Component,
admin = null,
...rest
}) => {
const dispatch = useDispatch();
const [role, setRole] = React.useState(null);
React.useEffect(
() => {
dispatch(getProfile())
.then(unwrapResult)
.then((res) => {
setRole(res.role);
})
.catch((err) => {
setRole("PROFILE_ERROR");
});
},
[ /* dependencies for when to re-request the profile*/ ]
);
return (
<Route
{...rest}
path={rest.path}
render={(props) => {
if ((role === "PRO" || role === "CLIENT") amp;amp; !admin) {
return <Layout {...props} />;
} else if (role === "ADMIN" amp;amp; admin) {
return <AdminLayout {...props} />;
} else if (role === "PROFILE_ERROR") {
return (
<Redirect
to={{
pathname: "/",
state: {
from: props.location
}
}}
/>
);
}
}}
/>
);
};