I have a Navbar component in my react app. I manage the admin state within the Navbar component. When I'm already on the Lag route and tries to route to Medlemar the admin part of the navbar disappears. This is because the admin state is getting reset when changing route. How can I prevent this?
Navbar component:
function Navbar({ data }) {
const [user, setUser] = useState(null)
const [admin, setAdmin] = useState(false)
const [passedData, setData] = useState(undefined)
useEffect(() => {
firebase.auth().onAuthStateChanged((user) => {
setUser(user)
})
if (passedData) {
console.log(passedData)
} else {
setData(data)
}
if (user) {
if(passedData !== undefined) {
firebase.firestore().collection('teams').doc(passedData.teamID).collection('members').doc(user.uid).get().then((snapshot) => {
const administrator = snapshot.get('role')
if (administrator === 'admin') {
setAdmin(true)
} else {
setAdmin(false)
}
})
}
}
}, [user])
return (
<nav className='navbar'>
<ul className='nav-menu-items'>
<li className="nav-text">
<Link to="/">
<AiIcons.AiFillDashboard size="1.4em" className="icon" />
<span>Dashboard</span>
</Link>
</li>
<li className="nav-text">
<Link to="/lag">
<AiIcons.AiOutlineTeam size="1.4em" className="icon" />
<span>Lag</span>
</Link>
</li>
<li className="nav-text">
<Link to="/profil">
<BsIcons.BsPerson size="1.4em" className="icon" />
<span>Profil</span>
</Link>
</li>
<li className="nav-text">
<Link to="/betaling">
<GiIcons.GiPayMoney size="1.4em" className="icon" />
<span>Betaling</span>
</Link>
</li>
</ul>
{admin ?
<>
<span className="admin-text">Admin</span>
<div className="navbar-divider"></div>
<ul className="nav-menu-items">
<li className="nav-text">
<Link to={{
pathname: `/lag/${data.teamID}/admin/medlemar`,
state: {
passedData: data,
}
}}>
<BsIcons.BsPeopleFill className="icon" size="1.4em" />
<span>Medlemar</span>
</Link>
</li>
</ul>
</>
:
null
}
</nav>
)
}
App.js
function App() {
return (
<>
<Router>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/logg-inn" component={Login} />
<Route path="/lag/:id" exact component={Team} />
<Route path="/profil" component={Profile} />
<Route path="/registrer-deg" component={Signup} />
<Route path="/lag" exact component={Teams} />
<Route path="/lag/:id/innstillingar" exact component={TeamSettings} />
<Route path="/lag/:id/betaling" exact component={Payment} />
<Route path="/lag/:id/arrangement" exact component={Events} />
<Route path="/lag/:id/admin/medlemar" component={Members} />
</Switch>
</Router>
</>
);
}
If you want to persist state inbetween the routes with your Navbar then you should use it as a wrapper component and wrap /lag routes with this.
Generaly it would be better to use React Context or any other state managing library to avoid future problems, but the solution I provided should be working.
Your Navbar component could take children(for wrapping purposes) and look like this per say:
function Navbar({ data, children }) {
const [user, setUser] = useState(null);
const [admin, setAdmin] = useState(false);
const [passedData, setData] = useState(undefined);
useEffect(() => {
firebase.auth().onAuthStateChanged((user) => {
setUser(user);
});
if (passedData) {
console.log(passedData);
} else {
setData(data);
}
if (user) {
if (passedData !== undefined) {
firebase
.firestore()
.collection('teams')
.doc(passedData.teamID)
.collection('members')
.doc(user.uid)
.get()
.then((snapshot) => {
const administrator = snapshot.get('role');
if (administrator === 'admin') {
setAdmin(true);
} else {
setAdmin(false);
}
});
}
}
}, [user]);
return (
<nav className="navbar">
<ul className="nav-menu-items">
<li className="nav-text">
<Link to="/">
<AiIcons.AiFillDashboard
size="1.4em"
className="icon"
/>
<span>Dashboard</span>
</Link>
</li>
<li className="nav-text">
<Link to="/lag">
<AiIcons.AiOutlineTeam size="1.4em" className="icon" />
<span>Lag</span>
</Link>
</li>
<li className="nav-text">
<Link to="/profil">
<BsIcons.BsPerson size="1.4em" className="icon" />
<span>Profil</span>
</Link>
</li>
<li className="nav-text">
<Link to="/betaling">
<GiIcons.GiPayMoney size="1.4em" className="icon" />
<span>Betaling</span>
</Link>
</li>
</ul>
{admin ? (
<>
<span className="admin-text">Admin</span>
<div className="navbar-divider"></div>
<ul className="nav-menu-items">
<li className="nav-text">
<Link
to={{
pathname: `/lag/${data.teamID}/admin/medlemar`,
state: {
passedData: data,
},
}}
>
<BsIcons.BsPeopleFill
className="icon"
size="1.4em"
/>
<span>Medlemar</span>
</Link>
</li>
</ul>
</>
) : null}
{children}
</nav>
);
}
and then your App would be looking something like this:
function App() {
return (
<>
<Router>
<Switch>
<Route path="/" exact component={Home} />
<Route path="/logg-inn" component={Login} />
<Route path="/lag/:id" exact component={Team} />
<Route path="/profil" component={Profile} />
<Route path="/registrer-deg" component={Signup} />
<Navbar>
<Route path="/lag" exact component={Teams} />
<Route path="/lag/:id/innstillingar" exact component={TeamSettings} />
<Route path="/lag/:id/betaling" exact component={Payment} />
<Route path="/lag/:id/arrangement" exact component={Events} />
<Route path="/lag/:id/admin/medlemar" component={Members} />
</Navbar>
</Switch>
</Router>
</>
);
}
Related
I am currently using react V6. I have a sidebar nav and a top bar nav. The top bar nav is supposed to display when the user has NOT been authenticated. The sidebar nav is only supposed to display when the user has logged in. But my sidebar nav is showing on for all routes and my top nav isn't displaying at all.
APP.JS
function App() {
const { user, authIsReady } = useAuthContext()
const theme = createTheme({
palette: {
mode: 'light',
},
typography: {
guideline: {
color: 'gray',
display: 'block',
},
},
});
return (
<ErrorBoudry>
<div className="App">
{authIsReady && (
<BrowserRouter>
{user && <Sidebar />}
<div className='container'>
<NavBar/>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route path="/login" element={<LoginPage />} />
<Route path="/register" element={<RegisterPage />} />
<Route path="/dashboard" element={
<ProtectedRoute>
<DashboardPage/>
</ProtectedRoute>
}/>
<Route path="/findMatch" element={
<ProtectedRoute>
<findMatchPage />
</ProtectedRoute>
}/>
<Route path="/profile" element={
<ProtectedRoute>
<ProfilePage />
</ProtectedRoute>
}/>
<Route path="/match-history" element={
<ProtectedRoute>
<MatchHistoryPage />
</ProtectedRoute>
}/>
</Routes>
</div>
{user && <OnlineUsers />}
</BrowserRouter>
)}
</div>
</ErrorBoudry>
);
}
export default App
NAVBAR.JS
export default function Navbar() {
const { logout, isPending } = useLogout()
const { user } = useAuthContext()
return (
<div className='navbar'>
<ul>
<li className='logo'>
<span>Gamers Meet</span>
</li>
{user ?
<li>
{!isPending && <button className='btn' onClick={logout}>logout</button>}
{isPending && <button className='btn' disabled>logging out</button>}
</li>
:
<>
<li>
<Link to='/landing'>Home</Link>
</li>
<li>
<Link to='/login'>login</Link>
</li>
<li>
<Link to='/register'>Register</Link>
</li>
</>
}
</ul>
</div>
)
}
SIDEBAR.JS
export default function Sidebar() {
const { user } = useAuthContext()
return (
<div className='sidebar'>
<div className='sidebar-content'>
<div className='user'>
<Avatar src={user.photoURL} />
<p>hey {user.displayName}!</p>
</div>
<nav className='links'>
<ul>
<li>
<NavLink exact to='/dashboard'>
<img src={DashboardIcon} alt='dashboard icon' />
<span>dashboard</span>
</NavLink>
</li>
<li>
<NavLink to='/findMatch'>
<img src={AddIcon} alt='add icon' />
<span>Find a Match</span>
</NavLink>
</li>
</ul>
</nav>
</div>
</div>
)
}
PROTECTEDROUTE.JS
import React from 'react';
import { Navigate } from 'react-router-dom';
const ProtectedRoute = ({ isLoggedIn, children }) => {
if (!isLoggedIn) {
return <Navigate to="/" replace />;
}
return children;
};
export default ProtectedRoute;
You can use same approach like you used in other components
export default function Sidebar() {
const { user } = useAuthContext()
return (
<>
{user &&
<div className='sidebar'>
<div className='sidebar-content'>
<div className='user'>
<Avatar src={user.photoURL} />
<p>hey {user.displayName}!</p>
</div>
<nav className='links'>
<ul>
<li>
<NavLink exact to='/dashboard'>
<img src={DashboardIcon} alt='dashboard icon' />
<span>dashboard</span>
</NavLink>
</li>
<li>
<NavLink to='/findMatch'>
<img src={AddIcon} alt='add icon' />
<span>Find a Match</span>
</NavLink>
</li>
</ul>
</nav>
</div>
</div>
}
</>
)
}
When the user goes to the url for "/films/:title" it displays MovieDetailContainer which is the component for the path above it and doesnt display its own component. When I flip around the order of the urls the reverse happens. Why is this? I assume its a nesting error but I cant seem to figure it out.
here is code for the routes and the code for the full App/js is below just incase.
<div className="container mt-3">
<Switch>
<Route exact path={["/", "/home"]} component={Home} />
<Route exact path="/login" component={Login} />
<Route exact path="/register" component={Register} />
<Route exact path="/profile" component={Profile} />
**<Route exact path="/films/:id" children={<MovieDetailContainer/>}/>
<Route exact path="/films/:title" children={<MovieListComponent/>}/>**
<Route path="/user" component={BoardUser} />
<Route path="/creator" component={BoardCreator} />
<Route path="/admin" component={BoardAdmin} />
</Switch>
</div>
import "bootstrap/dist/css/bootstrap.min.css";
import React, { useEffect, useState } from "react";
import { Link, Route, Switch } from "react-router-dom";
import styled from "styled-components";
import { useLocation } from 'react-router-dom';
// components
import Search from './components/search/Search'
import "./App.css";
// import AuthVerify from "./common/auth-verify";
import EventBus from "./common/EventBus";
import BoardAdmin from "./components/board-admin.component";
import BoardCreator from "./components/board-creator.component";
import BoardUser from "./components/board-user.component";
import Home from "./components/home.component";
import Login from "./components/login.component";
import MovieListComponent from "./components/films/movie-list.component";
import Profile from "./components/profile.component";
import Register from "./components/register.component";
import AuthService from "./services/auth.service";
import MovieInfoComponent from "./components/films/movie-info.component";
import MovieItem from "./components/films/movie-item.component";
import MovieDetailContainer from "./components/films/movie-detail-container.component"
const MovieListContainer = styled.div`
display: flex;
flex-direction: row;
flex-wrap: wrap;
padding: 30px;
gap: 25px;
justify-content: space-evenly; ;
`;
const App = () => {
const [showCreatorBoard, setShowCreatorBoard] = useState(false);
const [showAdminBoard, setShowAdminBoard] = useState(false);
const [currentUser, setCurrentUser] = useState(undefined);
const [locationState, setLocationState] = useState('')
const location = useLocation();
useEffect(() => {
const user = AuthService.getCurrentUser();
setLocationState(location.pathname)
if (user) {
setCurrentUser(user);
setShowAdminBoard(user.roles.includes("ROLE_MODERATOR"));
setShowAdminBoard(user.roles.includes("ROLE_ADMIN"));
}
EventBus.on("logout", () => {
this.logOut();
});
return () => {
EventBus.remove("logout");
};
}, []);
const logOut = () => {
AuthService.logout();
setShowCreatorBoard(false);
setShowAdminBoard(false);
setCurrentUser(undefined);
};
return (
<div>
<nav className="navbar navbar-expand navbar-dark bg-dark">
<Link to={"/"} className="navbar-brand">
Movie App
</Link>
<div className="navbar-nav mr-auto">
<li className="nav-item">
<Link to={"/home"} className="nav-link">
Home
</Link>
</li>
{showCreatorBoard && (
<li className="nav-item">
<Link to={"/mod"} className="nav-link">
Moderator Board
</Link>
</li>
)}
{showAdminBoard && (
<li className="nav-item">
<Link to={"/admin"} className="nav-link">
Admin Board
</Link>
</li>
)}
{currentUser && (
<li className="nav-item">
<Link to={"/user"} className="nav-link">
User
</Link>
</li>
)}
</div>
{/* passing a callback function to the Search component which will return
the result returned from the api. Keeping the movie list state in app.js to map the movies here */}
{locationState=='/register'||locationState=='/login'?null:<Search/>}
{currentUser ? (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/profile"} className="nav-link">
{currentUser.username}
</Link>
</li>
<li className="nav-item">
<a href="/login" className="nav-link" onClick={logOut}>
LogOut
</a>
</li>
</div>
) : (
<div className="navbar-nav ml-auto">
<li className="nav-item">
<Link to={"/login"} className="nav-link">
Login
</Link>
</li>
<li className="nav-item">
<Link to={"/register"} className="nav-link">
Sign Up
</Link>
</li>
</div>
)}
</nav>
<div className="container mt-3">
<Switch>
<Route exact path={["/", "/home"]} component={Home} />
<Route exact path="/login" component={Login} />
<Route exact path="/register" component={Register} />
<Route exact path="/profile" component={Profile} />
<Route exact path="/films/:id" children={<MovieDetailContainer/>}/>
<Route exact path="/films/:title" children={<MovieListComponent/>}/>
<Route path="/user" component={BoardUser} />
<Route path="/creator" component={BoardCreator} />
<Route path="/admin" component={BoardAdmin} />
</Switch>
</div>
{/* {selectedMovie && <MovieInfoComponent selectedMovie={selectedMovie} />} */}
{/*<AuthVerify logOut={this.logOut}/> */}
</div>
);
};
export default App;
The two paths "/films/:id" and "/films/:title" have the same specificity, so the one rendered first will be the one that is matched and rendered by the Switch component.
To resolve you need add something to differentiate them. I suggest a differentiating sub-path.
Example:
<div className="container mt-3">
<Switch>
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
<Route path="/profile" component={Profile} />
<Route path="/films/:title/:id" component={MovieDetailContainer}/>
<Route path="/films/:title" component={MovieListComponent}/>
<Route path="/user" component={BoardUser} />
<Route path="/creator" component={BoardCreator} />
<Route path="/admin" component={BoardAdmin} />
<Route path={["/", "/home"]} component={Home} />
</Switch>
</div>
App.js
return (
<Router history={createBrowserHistory}>
<Routes>
<Route path="/" element={<LandingPage />} />
<Route
path="/login"
element={
<LoginAuth redirectTo="/dashboard">
<SignIn set_token={setAuthToken} setUserType={setUserType} />
</LoginAuth>
}
/>
<Route path="/register" element={<SignUp />} />
<Route
path="/dashboard/*"
element={
<RequireAuth redirectTo="/login">
<UserDashboard />
</RequireAuth>
}
/>
<Route path="/register/subscription" element={<Package />} />
<Route path="/contact" element={<Contact />} />
<Route path="/pricing" element={<Pricing />} />
<Route path="/features" element={<Features />} />
</Routes>
</Router>
);
UserDashboard.js
when route is 'localhost../dashboard' it renders this component and in this useeffect I append URL with home so that home component render automatically.
useEffect(() => {
history("home");
}, []);
return (
<div className="dash-cont background-blue">
<header className="head-cont">
<div className="top-left-head">
<div className="left-header">
<a href="/" className="b-brand">
<span className="logo">SchoolSavvy</span>
</a>
<a href="#!" className="mob-toggler" onClick={onToggle}>
<Hamburger
className="hamburger-react"
toggled={isOpen}
toggle={setOpen}
/>
</a>
<div className="right_head_popup">
<MoreVertIcon />
</div>
</div>
<div className="right-header">
<NotificationsNoneOutlinedIcon className="notify-ico" />
<PersonOutlineOutlinedIcon className="person-ico" />
</div>
</div>
</header>
<div className="body-div">
<UserSidebar is_Open={isOpen} on_Toggle={onToggle} />
<div className="dash-info">
{/* Heading */}
<PathHeading />
<Routes>
<Route path="/home" element={<Home />} />
<Route path="/school/*" element={<SchoolComp />} />
<Route path="/student/*" element={<></>} />
<Route path="/parent/*" element={<></>} />
<Route path="/teacher/*" element={<></>} />
<Route path="/class/*" element={<></>} />
<Route path="/exam/*" element={<></>} />
<Route path="/attendance/*" element={<></>} />
<Route path="/timetable/*" element={<></>} />
</Routes>
</div>
</div>
</div>
);
Home.js
when this component is rendered, dispatch in useEffect causes infinite rendering, anyone knows what's the problem? Thanks
const Home = () => {
const dispatch = useDispatch();
useEffect(() => {
console.log("home rend");
dispatch(loadDashboard());
}, []);
return (
<>
{/* Cards */}
<Card />
<div className="sch_summary">
{/* Charts */}
<BarChart />
<NoticeBoard />
</div>
<Calendar />
</>
);
};
Here is loadDashboard action which is dispatched by useEffect
export const loadDashboard = () => async (dispatch, getstate) => {
try {
dispatch({
type: actionType.DASHBOARD_REQ,
});
console.log(`tokennn: ${getstate().user.token}`);
const { data } = await axios.get("/v1/user/dashboard/detail", {
headers: {
Authorization: `Bearer ${getstate().user.token}`,
},
});
dispatch({
type: actionType.DASHBOARD_SUCCESS,
payload: data.user,
});
} catch (error) {
console.log(`falii: ${error}`);
dispatch({
type: actionType.DASHBOARD_FAILURE,
payload: error.response.data,
});
}
};
One solution is to add the dispatch actions that cause infinite rerender to ref using useRef.
import { useRef } from 'react';
function useAddFnToRef(fn) {
const refProps = useRef({ fn });
return refProps.current.fn;
}
const Home = () => {
const dispatch = useDispatch();
const onLoadDashboard = useAddFnToRef(()=>dispatch(loadDashboard()))
useEffect(() => {
console.log("home rend");
onLoadDashboard();
}, [onLoadDashboard]);
return (
<>
{/* Cards */}
<Card />
<div className="sch_summary">
{/* Charts */}
<BarChart />
<NoticeBoard />
</div>
<Calendar />
</>
);
};
I am trying to figure out how to have three users access the web application that I have created. I would like for there to be an admin user, student user, and a public user. Each user has a different set of pages within their navigation bar. I have already been able to set up navigation for a student user and a public user but I am struggling to figure out how to add an admin user and configure the specific pages in the navigation bar for the admin user as well. Here is the following code:
App.js:
{/* using authcontext from the context api */}
export const authContext = createContext();
{/* hold the object for the authentication value */}
function ProvideAuth({ children, auth, setisAuth }) {
const authValue = {
auth,
setisAuth
};
return (
<authContext.Provider value={authValue}> {/* calling value from context api */}
{children}
</authContext.Provider>
);
}
function App() {
let isLoggedIn = localStorage.getItem('isauthenticated');
{/* setting the state of isauth to the variable isLoggedin */}
const [isAuth,setisAuth] = useState(isLoggedIn);
// const isLoggedIn = localStorage.getItem('isauthenticated');
// let isLoggedIn;
// useEffect(() => {
// isLoggedIn = localStorage.getItem('isauthenticated');
// })
return (
<ProvideAuth auth={isAuth} setisAuth={setisAuth}>
<Router>
<Navbar />
<Switch>
<Route path="/" exact component={Home}/>
<Route path="/login" exact component={Login}/>
{/* { isLoggedIn != "true" ? (<Route path="/login" exact component={Login}/>) : <></> } */}
<Route path="/sign-up" exact component={SignUp}/>
<PrivateRoute path="/virtual-trip" exact component={VirtualTrip} isAuth={isAuth}/>
<PrivateRoute path="/step1" exact component={Step1} isAuth={isAuth}/>
<PrivateRoute path="/step2" exact component={Step2} isAuth={isAuth} />
<PrivateRoute path="/step3" exact component={Step3} isAuth={isAuth}/>
<PrivateRoute path="/step4" exact component={Step4} isAuth={isAuth}/>
{/* <PrivateRoute path="/busconvo" exact component={BusConversation} isAuth={isAuth}/> */}
<PrivateRoute path="/complete" exact component={CompleteTrip} isAuth={isAuth}/>
<Route path="/contact" exact component={Contact}/>
<Route path="/resources" exact component={Resources} isAuth={isAuth}/>
<Route path="/forgotPassword" exact component={ForgotPassword}/>
{/* <PrivateRoute path="/profile" component={Profile} /> */}
<Route path="/resources" exact component={Resources}/>
<Route path="/about-me" exact component={AboutMe}/>
<PrivateRoute path="/scheduler" exact component={Scheduler} isAuth={isAuth}/>
<PrivateRoute path="/profile" exact component={Profile} isAuth={isAuth}/>
<Route path="/recruitment" exact component={Recruitment}/>
<Route path="/field-school" exact component={FieldSchool}/>
<Route path="/Home2" exact component={Home2}/>
<Route path="/video1" exact component={Video1} isAuth={isAuth} />
<Route path="/video2" exact component={Video2} isAuth={isAuth}/>
<Route path="/video3" exact component={Video3} isAuth={isAuth}/>
<Route path="/video4" exact component={Video4} isAuth={isAuth}/>
<Route path="/video5" exact component={Video5} isAuth={isAuth}/>
<Route path="/video6" exact component={Video6} isAuth={isAuth}/>
<Route path="/video7" exact component={Video7} isAuth={isAuth}/>
<Route path="/video8" exact component={Video8} isAuth={isAuth}/>
<Route path="/video9" exact component={Video9} isAuth={isAuth}/>
<Route path="/taxiconvo" exact component={TaxiConversation} isAuth={isAuth}/>
<Route path="/busconvo2" exact component={BusConvo2} isAuth={isAuth}/>
<Route path="/student-scheduler" exact component={StudentScheduler} isAuth={isAuth}/>
<Route path="/busconvo2spanish" exact component={BusConvo2Spanish} isAuth={isAuth}/>
<Route path="/taxiconvospanish" exact component={TaxiConversationSpanish} isAuth={isAuth}/>
<Route path="/resetPassword/:email/:token" exact component={ResetPassword}/>
<PrivateRoute path="/logout" exact component={Logout}/>
{/* <Route path="/Video" exact component={Video}/> */}
{/* { isLoggedIn == "true" ? (<PrivateRoute path="/virtual-trip" exact component={VirtualTrip}/>) : <></> } */}
<Route path="/resetPassword/:email/:token" exact component={ResetPassword}/>
</Switch>
</Router>
</ProvideAuth>
);
}
export default App;
Login.js
const login = () => {
Axios({
method: "POST",
data: {
username: loginUsername,
password: loginPassword,
},
withCredentials: true,
url: "http://localhost:4000/login",
}).then((res) => {
console.log(res);
setError(res.data);
//Redirecting to home after successful authentication
if(res.data === "Successfully authenticated!"){
{/* setting the local storage item to true */}
localStorage.setItem('isauthenticated', true);
{/* changing the global state to true as well */}
auth.setisAuth(true);
history.push("/");
// window.location.reload(false);
}
});
};
Logout.js
const logout = () => {
{/* removing the item from local storage */}
localStorage.removeItem('isauthenticated');
{/* setting global state to false because you're logged out */}
auth.setisAuth(false);
history.push("/");
// window.location.reload(false);
}
Navigation.js
<nav className="navbar">
<div className = "navbar-container">
<Link to="/" className="navbar-logo" onClick={closeMobileMenu}>
WAYNE STATE UNIVERSITY
</Link>
<div className='menu-icon' onClick={handleClick}>
<i className={click ? 'fas fa-times' : 'fas fa-bars'} />
</div>
<ul className={click ? 'nav-menu active' : 'nav-menu'}>
<li className='nav-item'>
<Link to='/recruitment' className='nav-links' onClick={closeMobileMenu}>
About
</Link>
</li>
<li className='nav-item'>
<Link to='/contact' className='nav-links' onClick={closeMobileMenu}>
Contact
</Link>
</li>
{ !auth.auth ? ( <li className='nav-item'>
<Link to='/sign-up' className='nav-links' onClick={closeMobileMenu}>
Sign-Up
</Link>
</li> ) : <></> }
{ !auth.auth ? ( <li className='nav-item'>
<Link to='/login' className='nav-links' onClick={closeMobileMenu} >
Login
</Link>
</li> ) : <></>}
{ auth.auth ? ( <li className='nav-item'>
<Link to='/virtual-trip' className='nav-links' onClick={closeMobileMenu}>
Virtual Trip
</Link>
</li> ) : <></> }
{ auth.auth ? ( <li className='nav-item'>
<Link to='/resources' className='nav-links' onClick={closeMobileMenu}>
Resources
</Link>
</li> ) : <></> }
{ auth.auth ? ( <li className='nav-item'>
<Link to='/scheduler' className='nav-links' onClick={closeMobileMenu}>
Scheduler
</Link>
</li> ) : <></> }
<li className='nav-item'>
<Link to='/about-me' className='nav-links' onClick={closeMobileMenu}>
About Director
</Link>
</li>
{ auth.auth ? ( <li className='nav-item'>
<Link to='/' className='nav-links' onClick={logout}>
Logout
</Link>
</li> ) : <></> }
{ auth.auth ? ( <li className='nav-item'>
<Link to='/profile' className='nav-links' onClick={closeMobileMenu}>
<i className="fas fa-user"></i>
</Link>
</li> ) : <></> }
</ul>
</div>
</nav>
Are you using some kind of database to store a user? If so you can check for role after login an then display the content for admin, user, whatever ... This can be done by conditional logic eg.
user === 'admin' ? <p>Admin page</p> : <p>Student page</p>
First of all, I am using stateless components (functional)
The problem I am running into is this:
When going to another route via Link component I am getting the blank page, and after refreshing the page the component loads.
I have all my routes inside the App.js
<BrowserRouter>
<Switch>
<Route path="/panele" component={Dashboard} />
<Route path="/prisijungimas" component={Login} />
<Route path="/skelbimas/:id">
<HeadLine>
<h1>
SURASK DARBĄ <span>GREIČIAU</span> IR <span>EFEKTYVIAU</span>
</h1>
</HeadLine>
<SingleJobPost />
</Route>
<Route exact path="/" component={AllJobPosts} />
</Switch>
</BrowserRouter>
);
To be honest I am kinda desperate over here. When I don't have the exact attribute on the route component pages are loading - but it is stacking on each other - this is not ok for me.
EDIT:
The Dashboard component:
const Dashboard = props => {
let data = JSON.parse(sessionStorage.getItem("user"));
let history = useHistory();
let { path, url } = useRouteMatch();
let header = new URL(window.location.href).searchParams.get("header");
return (
<>
{data === null ? (
<>{history.push("/prisijungimas")}</>
) : (
<DashboardWrapper>
<Navigation>
<DashboardLogo>
<img src={dashboardLogo} />
<h1>Valdymo panelė</h1>
</DashboardLogo>
<nav>
<ul>
<li>
<Link to="/panele/skelbimuvaldymas?header=Valdykite sukurtus darbo pasiūlymus">
Sukurtų darbo pasiūlymų valdymas
</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Pranešimai</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Pagalbos centras</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Vartotoju valdymas</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Logs</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Mano profilis</Link>
</li>
</ul>
</nav>
</Navigation>
<EditorWindow>
<EditorHeader>
<h1>{header}</h1>
</EditorHeader>
<Editor id="style-1">
<Switch>
<Route path={`${path}/skelbimas`}>
<JobPost />
</Route>
<Route
path={`${path}/skelbimuvaldymas`}
component={ControlJobPost}
/>
</Switch>
</Editor>
</EditorWindow>
</DashboardWrapper>
)}
</>
);
};
I fixed the problem this way:
It works with the functional component as well - I approached it this way:
First of all, make sure to make an if statement to check it the values are loaded if it is not that render empty block otherwise render the actual component with all the data.
{!posts ? (
<></>
) : ( COMPONENT) }
The secound thingy which fixed the problem was - in uedEffect method calling async
function, not doing all the logic inside the method it self.
const fetchData = async () => {
const result = await axios("http://localhost:1337/jobposts?confirmed=true");
setPosts(result.data);
};
useEffect(() => {
fetchData();
}, []);
Make the component stateful and handle the data via state.
const Dashboard = props => {
const [data, setData] = useState();
let history = useHistory();
let { path, url } = useRouteMatch();
useEffect(() => {
let data = JSON.parse(sessionStorage.getItem("user"));
setData(() => {
data
});
}, []);
let header = new URL(window.location.href).searchParams.get("header");
return (
<>
{data === null ? (
<>{history.push("/prisijungimas")}</>
) : (
<DashboardWrapper>
<Navigation>
<DashboardLogo>
<img src={dashboardLogo} />
<h1>Valdymo panelė</h1>
</DashboardLogo>
<nav>
<ul>
<li>
<Link to="/panele/skelbimuvaldymas?header=Valdykite sukurtus darbo pasiūlymus">
Sukurtų darbo pasiūlymų valdymas
</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Pranešimai</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Pagalbos centras</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Vartotoju valdymas</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Logs</Link>
</li>
<li>
{" "}
<Link path="/panele/valdymas">Mano profilis</Link>
</li>
</ul>
</nav>
</Navigation>
<EditorWindow>
<EditorHeader>
<h1>{header}</h1>
</EditorHeader>
<Editor id="style-1">
<Switch>
<Route path={`${path}/skelbimas`}>
<JobPost />
</Route>
<Route
path={`${path}/skelbimuvaldymas`}
component={ControlJobPost}
/>
</Switch>
</Editor>
</EditorWindow>
</DashboardWrapper>
)}
</>
);
};