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>
)}
</>
);
};
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>
}
</>
)
}
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>
</>
);
}
I am making an advertising website with reusable components that load with different graphics depending on what page it is. I am using react-router-dom Route exact path. I imagine i need to be able to read the state of that with my useEffect,[]. So how do i pass down the state so its able to be read by the component.
Please note that the component Hero appears in the functions for Home, Consultants and Solutions
const Hero = props => {
useEffect(() => {
console.log(props);
}, []);
return (
<Fragment>
<div className='grid-hero'>
<Fragment>
<div className='overlay'>
<div>
<p className='bg-dark'></p>
<img src={{ homeimg } || { consimg } || { solsimg }} alt='' />
</div>
</div>
</Fragment>
<Router>
<Fragment>
<Navbar />
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/consultants' component={Consultants} />
<Route exact path='/solutions' component={Solutions} />
<Route exact path='/contactus' component={ContactUs} />"
</Switch>
</Fragment>
</Router>
<div
className={
{pathname === "/" && ("grid-home")}
{pathname === "/consultants" && ("grid-consultants")}
{pathname === "/solutions" && ("grid-solutions")}
}>
maybe this is what you're looking for:
I've added Hero as top-level image component where your image would switch. I don't have the images, so I used strings, but if you import images like JSX, you'll be able to use this code by removing the img strings inside my Hero dummy component.
adding reference image import syntax for help:
import img from './img.png';
complete example:
import React, { Fragment } from "react";
import {
BrowserRouter as Router,
Route,
Link,
useLocation
} from "react-router-dom";
function BasicExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/contactus">ContactUs</Link>
</li>
<li>
<Link to="/solutions">Solutions</Link>
</li>
</ul>
<hr />
<Hero />
<Route exact path="/" component={Home} />
<Route path="/contactus" component={ContactUs} />
<Route path="/solutions" component={Solutions} />
</div>
</Router>
);
}
const Hero = () => {
const homeimg = "HOME_IMAGE";
const consimg = "CONTACT_US_IMAGE";
const solsimg = "SOLUTIONS_IMAGE";
let img = null;
const location = useLocation();
if (location.pathname === "/") img = homeimg;
else if (location.pathname === "/contactus") img = consimg;
else if (location.pathname === "/solutions") img = solsimg;
return (
<Fragment>
<h3>{location.pathname}</h3>
<div className="grid-hero">
<Fragment>
<div className="overlay">
<div>
<p className="bg-dark" />
{img}
</div>
</div>
</Fragment>
</div>
</Fragment>
);
};
function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}
function ContactUs() {
return (
<div>
<h2>ContactUs</h2>
</div>
);
}
function Solutions() {
return (
<div>
<h2>Solutions</h2>
</div>
);
}
export default BasicExample;
codepen-link
I am pretty new to react-router. I created a single page with nav bars that can navigate to the either of two pages. In one of the pages, I have a series of link that should direct to another component. My app component deals with the initial routing
<Router>
<nav className ="nav">
<Link to='/' className="nav__nav-link-logo link"><img src={Logo} className="nav__nav-logo" alt="A figure that depicts school"></img></Link>
<button onClick={this.handleBarClick} className="nav__nav-bar-icon link"><FontAwesomeIcon icon={faBars} /></button>
<div className="nav__text-and-icon" style={{display : this.state.navTextDisplay}}>
<Link to = '/' className="nav__text link"><FontAwesomeIcon icon={faHome} className="icon" /> Home </Link>
<Link to = '/pages/Contact/Contact' className="nav__text link"><FontAwesomeIcon icon={faPhoneAlt} className="icon"/> Contact the Dev</Link>
</div>
</nav>
<Switch>
<Route exact path='/' component = { Home } />
<Route exact path='/' component = { Home } />
<Route path='/pages/Contact' component = { Contact } />
<Route component={NotFoundPage}/>
</Switch>
</Router>
then the home component renders a list of links I want to navigate to another component entirely. PS : this is not about nest routing
my list of links code is
render() {
return (
<Fragment>
{/**
* #param item the indiviual school generated from the API
*/}
{this.state.apiResponse.map((item, index) => {
return (
<Fragment>
<li key={item.schoollid}>
<Link
to="/component/SchoolDetails/SchoolDetails"
className="each-school"
>
<SchoolTemplate item={item} />
</Link>
</li>
<Route
path="/component/SchoolDetails"
render={props => (
<SchoolDetails {...props} details={item} />
)}
// component={SchoolDetails}
/>
</Fragment>
);
})}
</Fragment>
);
But then my routes is linking the individual links to my 404 (not found page)
Try this it worked for me ,
User Navbar React bootstrap plugin for the menu bar navigation ,
npm package: import {Navbar, Nav,NavItem, NavDropdown, MenuItem,Glyphicon, Label} from 'react-bootstrap';
`
</Navbar.Header>
<Navbar.Collapse>
<Nav>
<NavItem eventKey={1} href="#/Dashboard">
Dashboard
</NavItem>
<NavDropdown eventKey={3} title="Tickets" id="basic-nav-dropdown">
<MenuItem eventKey={3.1}>
<NavLink exact to={ "/Home"}>Home</NavLink>
</MenuItem>
<MenuItem eventKey={3.2}>
<NavLink exact to={ "/Gallary"}>Gallary</NavLink>
</MenuItem>
</Nav>
</NavDropdown>
</Navbar.Collapse>
<NavDropdown eventKey={3} title="Tickets" id="basic-nav-dropdown">
<MenuItem eventKey={3.1} ><NavLink exact to={"/Home"} >Home</NavLink></MenuItem>
<MenuItem eventKey={3.2}><NavLink exact to={"/Gallary"}>Gallary</NavLink></MenuItem>
</Nav>
npm package:
import {Route, BrowserRouter,NavLink,HashRouter , Switch} from 'react-router-dom';
`
try this.
class APIRoutes extends React.Component {
...
render() {
return (
<Switch>
{this.state.apiResponse.map((item, index) => {
return (
<Fragment>
...
<Route
path="/component/SchoolDetails"
render={props => (
<SchoolDetails {...props} details={item} />
)}
/>
</Fragment>
);
})}
</Switch>
);
}
And the component that have Router
<Router>
...
<Switch>
<APIRoutes />
<Route exact path='/' component={Home}/>
<Route path='/pages/Contact' component={Contact}/>
<Route component={NotFoundPage}/>
</Switch>
</Router>
I have a Dasboard component where I have React-router
<Link/> components that are linking to
http:<procjethos>/team
Inside <Team/> component I have a <Link/> components that should link to
http:<projecthost>/list/:listId
But instead, it inherits from previous link and I get
http<projecthost>/team/list/:listId
// Dashboard.jsx
render() {
const { shoppingLists, teams } = this.props;
return (
<Fragment>
<Toolbar isHomePage/>
<div className="wrapper">
<div className="dashboard">
<h2 className="dashboard__heading">
<TeamIcon />
Cohorts
</h2>
<ul className="dashboard__list">
{_map(teams, team => (
<li className="dashboard__list-item" key={team._id}>
<Link to={`team/${team._id}`}>
<CardItem name={team.name} />
</Link>
</li>
))}
</ul>
</div>
</div>
</Fragment>
);
// Team.jsx
<Fragment>
<Toolbar />
<div>
Cohort of id:
{id}
<ul>
{_map(lists, list => (
<li className="dashboard__list-item" key={list._id}>
<Link to={`list/${list._id}`} replace>
<CardItem name={list.name} />
</Link>
</li>
))}
</ul>
</div>
</Fragment>
How to achieve the desired behavior in React-Router 4 with nested LINKs?
Add a / before link path
<Link to={`/list/${list._id}`} replace>
<CardItem name={list.name} />
</Link>