Matched leaf route at location "/Gallary" does not have an element - reactjs

I am Trying to reach the <Gallery/> Component using a Menu button with React-Router Link
so the code is for the Menu
Menu.jsx
import { Link } from 'react-router-dom';
export default function Menu({ menuOpen, setMenuOpen }) {
return (
<div className={"menu " + (menuOpen && "active")}>
<ul>
<li onClick={() => setMenuOpen(false)}>
<Link to="/">Home Page</Link>
</li>
<li onClick={() => setMenuOpen(false)}>
<Link to="/Gallery">Gallery</Link>
</li>
</ul>
</div>
);
}
and the code for APP.jsx:
import './App.scss';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import { useState } from 'react';
import Gallery from './components/Gallery/Gallery';
import Menu from './components/menu/Menu';
import Topbar from './components/topbar/Topbar';
import FooterComp from './components/Footer/FooterComp';
const App = () => {
const [menuOpen, setMenuOpen] = useState(false);
return (
<>
<Router>
<Topbar menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<Menu menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/Gallery" elemtent={<Gallery />} />
</Routes>
<FooterComp />
</Router>
</>
)
}
export default App
When I click the button which is supposed to route to the <Gallery/> Component it routes to an empty component and this warning is displayed in the console
Matched leaf route at location "/Gallery" does not have an element. This means it will render an with a null value by default resulting in an "empty" page.
I searched for this problem and only router-dom version related fixes are there and you can see I'm using the correct v6 props and components.

You have a typo. element
Change
<Route path="/Gallery" elemtent={<Gallery />} />
to
<Route path="/Gallery" element={<Gallery />} />

Related

Adding routes inside a component in react router dom version 6

I am trying to migrate from react router 5 to react router 6. I coded a simple frontend where only if the login button is clicked you can go to the profile page. and inside profile page there are two links to view profile and edit profile.
//App.js
import './App.css';
import Header from './components/Header';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage';
import Profile from './pages/Profile';
import NotFoundPage from './pages/NotFoundPage';
import Post from './pages/Post';
import GroupProfile from './pages/GroupProfile';
import {BrowserRouter as Router, Routes, Route, Navigate} from 'react-router-dom';
import {useState} from 'react';
function App(){
const [login, setLogin] = useState(false);
const [glogin, setGlogin] = useState(false);
return(
<div className="App">
<Router>
<Header />
<button onClick={() => setLogin(!login)}> {!login?"Login":"Logout"} </button>
<span> | </span>
<button onClick={() => setGlogin(!glogin)}> {!glogin?"GroupLogin":"GroupLogout"} </button>
<Routes>
<Route path='/' element={<HomePage />} />
<Route path='/about' element={<AboutPage />} />
{/*<Route path='/prof'>
{login ? <Profile />:<Navigate to='/' />} Nope, in react_router_dom6 putting other things rather than function that returns pages are not valid
</Route>*/}
<Route path='/group' element={<GroupProfile g_login={glogin} />} />
<Route path='/prof/*' element={<Profile l_ogin={login} />} />
<Route path='/post/:id' element={<Post />} />
<Route path='*' element={<NotFoundPage />} />
</Routes>
</Router>
</div>
)
}
export default App;
And these are groupprofile page and profile page.
GroupProfile.js
import React from 'react';
import {useEffect} from 'react';
import {useNavigate} from 'react-router-dom';
function GroupProfile({ g_login }){
let nav = useNavigate();
useEffect(() => {
if (!g_login) {
nav("/");
}
},[g_login, nav]) //you know useEffect hook, if dependancy list is given, when they change then hook will be triggered.
return(
<div>
<p>This is the GroupProfile</p>
</div>
)
}
export default GroupProfile;
Profile.js
import React, {useEffect} from 'react';
import {Route, Routes, useRouteMatch, Link, useNavigate, useLocation} from 'react-router-dom';
import EditProfile from '../components/EditProfile';
import ViewProfile from '../components/ViewProfile';
/*
function Profile(){
const { path, url } = useRouteMatch();
//console.log(useRouteMatch());
return(
<>
<h3>Profile Page</h3>
<ul>
<li><Link to={`${url}/viewprofile`}>View Profile</Link></li>
<li><Link to={`${url}/editprofile`}>Edit Profile</Link></li>
</ul>
<Route path={`${path}/viewprofile`} component={ViewProfile} />
<Route path={`${path}/editprofile`} component={EditProfile} />
</>
)
}
*/
function Profile({l_ogin}){
let nav = useNavigate();
let location = useLocation();
//console.log(location)
useEffect(() => {
if (!l_ogin) {
nav("/");
}
},[l_ogin, nav]) //you know useEffect hook, if dependancy list is given, when they change then hook will be triggered.
return(
<div>
<h1>Congrats! you made it to the profile page mate...</h1>
<ul>
<li><Link to={`${location}/viewprofile`}>View Profile</Link></li>
<li><Link to={`${location}/editprofile`}>Edit Profile</Link></li>
</ul>
<Routes>
<Route path={`${location}/viewprofile`} element={<ViewProfile />} />
<Route path={`${location}/Editprofile`} element={<EditProfile />} />
</Routes>
</div>
)
}
export default Profile;
I have commented the Profile component that works in react router version 5 and it is supposed to navigate to /prof/viewprofile when View Profile link is clicked. ViewProfile.js and EditProfile.js are simple components
ViewProfile.js
import React from "react";
const ViewProfile = () => {
return(
<div>
<h3><i>This is what you have to see in the profile.</i></h3>
</div>
)
}
export default ViewProfile;
The code I used in react router 5 works fine and when I clicked View Profile it navigates to /prof/viewprofile without any problem. But when I use react router 6 it doesn't navigate to /prof/viewprofile and it just stays in the /prof, but url changes to something like /prof/[object%20Object]/viewprofile. Can someone show me what am I doing wrong here?
location is an object, and if this is what you were trying to use you'd need location.pathname, but this is not what you want to try and use to build paths for descendent routes. When rendering Routes components and descendent routes, the routes are already built relative to the parent route. There is no need to try and build/implement the relative-ness yourself.
Example:
function Profile({ l_ogin }){
const navigate = useNavigate();
useEffect(() => {
if (!l_ogin) {
navigate("/", { replace: true });
}
}, [l_ogin, navigate]);
return(
<div>
<h1>Congrats! you made it to the profile page mate...</h1>
<ul>
<li><Link to="viewprofile">View Profile</Link></li>
<li><Link to="editprofile">Edit Profile</Link></li>
</ul>
<Routes>
<Route path="viewprofile" element={<ViewProfile />} />
<Route path="editprofile" element={<EditProfile />} />
</Routes>
</div>
);
}
If you wanted to keep the first route implementation you were trying to use then this is the correct syntax. You still need to render the routed content on the element prop.
<Route
path='/prof'
element={login ? <Profile /> : <Navigate to='/' replace />}
/>
I realize these are the docs for v5: https://v5.reactrouter.com/web/api/Hooks/uselocation
But I suspect that before you didn't use the useLocation() hook by default?
From the url that gets parsed you can tell that the location variable not a string but an object [object%20Object]
Could you try: ${location.pathname} where you now have ${location} ?

Why do my Link To links not work in React-Router?

Trying to create an about page for a website im working on, I found this solution on Stack but it does not work for me. I was using an outdated tutorial for my original code, this is my current code:
About.js:
import React from "react";
import { Link, Route, useMatch } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
//const match = useMatch('/');
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to={'about-app'}>About App</Link>
</li>
<li>
<Link to={'about-author'}>About Author</Link>
</li>
</ul>
<Route path={':slug'}>
<SinglePage />
</Route>
</div>
);
};
export default About;
Index.js where I am rendering the component:
import React from "react";
import ReactDOM from "react-dom";
import TodoContainer from "./functionBased/components/TodoContainer"; // Component file
import "./functionBased/App.css"; // Style sheet
import { HashRouter as Router, Routes, Route } from "react-router-dom"; // Router file
import About from "./functionBased/pages/About";
import NotMatch from "./functionBased/pages/NotMatch";
ReactDOM.render(
<React.StrictMode>
<Router>
<Routes>
<Route exact path="/" element={<TodoContainer />} />
<Route path="/about/*" element={<About />} />
<Route path="*" element={<NotMatch />} />
</Routes>
</Router>
</React.StrictMode>,
document.getElementById("root")
);
Issues
The About component is directly rendering a Route component. The Route component can only be rendered by a Routes component or another Route component as a nested route.
The react-router-dom#6 Route components render their content on the element prop.
Solution
Import the Routes component and wrap the descendent Route component rendered by `About.
Render SinglePage on the route's element prop.
Example:
import React from "react";
import { Link, Routes, Route } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to="about-app">About App</Link>
</li>
<li>
<Link to="about-author">About Author</Link>
</li>
</ul>
<Routes>
<Route path=":slug" element={<SinglePage />} />
</Routes>
</div>
);
};
export default About;
Alternative
You could alternatively move the SinglePage route out to the main router as a nested route (instead of where it is as a descendent route).
Example:
import React from "react";
import { Link, Outlet } from "react-router-dom";
import SinglePage from "./SinglePage";
const About = () => {
return (
<div className="about__content">
<ul className="about__list">
<li>
<Link to="about-app">About App</Link>
</li>
<li>
<Link to="about-author">About Author</Link>
</li>
</ul>
<Outlet />
</div>
);
};
export default About;
...
<Router>
<Routes>
<Route path="/" element={<TodoContainer />} />
<Route path="/about" element={<About />}>
<Route path=":slug" element={<SinglePage />} />
</Route>
<Route path="*" element={<NotMatch />} />
</Routes>
</Router>
You are defining the routes with /about/* and accessing them with about-something which does not exist at all, add \about\author in to for Link.

My react onClick navigate shows URL, but does not render component

I am new to React router here and I am trying to make clicking on a recipe in my 'BrowseRecipes' page redirect to a page dedicated to that recipe. However, when I click on the recipe, the URL shows the correct URL /browse/${recipeID}, but the page I assign to this route does not render. Only the /browse page with a list of all the recipes renders. Does anyone know why?
Here is my APP.js
import AddNewRecipe from './components/AddNewRecipe'
import BrowseRecipes from './components/BrowseRecipes'
import { currentState } from './components/redux';
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Switch, Route, Routes, Link, useParams} from "react-router-dom";
import AuthReqPage from "./components/AuthReqPage"
import Navbar from "./components/Navbar"
import RecipePage from "./components/BrowseRecipes/RecipePage"
import PageNotFound from "./components/PageNotFound"
function App(props) {
return (
<Router>
<div className="App">
<Navbar />
<Routes>
<Route path='/add' element={<AddNewRecipe />} />
<Route path='/' element={<BrowseRecipes />} />
<Route path='/browse' element={<BrowseRecipes />}>
<Route path=':recipeID' element={<RecipePage />}/>
</Route>
<Route path='/authrequired' element={<AuthReqPage />} />
<Route path='/*' element={<PageNotFound />} />
</Routes>
</div>
</Router>
);
}
export default App;
Here is my BrowseRecipe component/page:
export function BrowseRecipes (props){
console.log('browseRecipe running')
let navigate = useNavigate()
let params=useParams()
console.log(params.recipeID)
if(props.recipeStore.length>0)
{
var displayRecipes = props.recipeStore.map(
elem=>
{
return (<li key={elem.recipeID} className='recipeDisplayBox' onClick={()=>navigate(`/browse/${elem.recipeID}`)}>
{elem.title},
Prep: {elem.prepTime.numeral} {elem.prepTime.unit}
</li>)
}
)
}
return(
<div>
<h1>Browse Recipes</h1>
<h2>Your recipes:</h2>
<ul>
{displayRecipes}
</ul>
</div>
)
}
const mapStateToProps=(state)=>{
return {recipeStore: state.recipe}}
export default connect(mapStateToProps)(RequireAuth(BrowseRecipes))
And here is the individual recipe page that failed to render:
export function RecipePage (props){
console.log('RecipePage running')
let params=useParams()
return(
<div>
<h1>{params.recipeID}</h1>
</div>
)
}
const mapStateToProps=(state)=>{
return {recipeStore: state.recipe}}
export default connect(mapStateToProps)(RequireAuth(RecipePage))
"RequireAuth" here is a higher-order component that redirects the page to 'Please Sign In' page if the user is not signed in.
Did I misunderstand something about the use of UseParams? Please help me shed some light! Thank you very much
You've rendered the RecipePage component on a nested route from the "/browse" route rendering the BrowseRecipes component.
<Route path='/browse' element={<BrowseRecipes />}>
<Route path=':recipeID' element={<RecipePage />}/>
</Route>
In this configuration the BrowseRecipes is required to render an Outlet component for the nested routes to be rendered into.
Example:
import { Outlet, useNavigate, useParams } from 'react-router-dom';
export function BrowseRecipes (props) {
const navigate = useNavigate();
const params = useParams();
let displayRecipes;
if (props.recipeStore.length) {
displayRecipes = props.recipeStore.map(elem => {
return (
<li
key={elem.recipeID}
className='recipeDisplayBox'
onClick={() => navigate(`/browse/${elem.recipeID}`)}
>
{elem.title},
Prep: {elem.prepTime.numeral} {elem.prepTime.unit}
</li>
);
});
}
return (
<div>
<h1>Browse Recipes</h1>
<h2>Your recipes:</h2>
<ul>
{displayRecipes}
</ul>
<Outlet /> // <-- nested routes render here
</div>
);
}
If you don't want to render both BrowseRecipes and RecipePage at the same time, then create a nested index route specifically for BrowseRecipes.
Example:
<Route path='/browse'>
<Route index element={<BrowseRecipes />} /> // <-- "/browse"
<Route path=':recipeID' element={<RecipePage />} /> // <-- "/browse/:recipeID"
</Route>
For more information, see:
Index Routes
Layout Routes

When a React button is clicked the url/route changes. But the content associated with the url/route does not render

I am new to react, and I have many videos, but I can not find my problem. I want to open the contact me section when I click the contact me button present on the main page. When I click on the contact me button, it changes the route in the URL but does the opens the page.
When I try to open the same page by clicking the link present in the navbar, it works.
I am cleaning up while posting the question to maintain readability.
This is my App.js
import React from 'react';
import Nav from './components/Nav';
// Import Pages
import AboutMe from './pages/AboutMe';
import MyWork from './pages/MyWork';
import ContactMe from './pages/ContactMe';
// Router
import {BrowserRouter, Route, Switch, useLocation } from "react-router-dom";
function App() {
const location = useLocation();
return (
<div className="App">
<GlobalStyle />
<Nav />
<BrowserRouter>
<Switch location={location} key={location.pathname}>
<Route path="/" exact>
<AboutMe />
</Route>
<Route path="/work" exact>
<MyWork />
</Route>
<Route path="/contact" exact>
<ContactMe />
</Route>
</Switch>
</BrowserRouter>
</div>
);
}
This is my AboutSection.
In my about section, when I click on my button, it enters /contact but does not open the page, but when I try to open the same route while clicking on the link from the navbar, it opens the link.
import React from "react";
import { Link } from "react-router-dom";
//Images
const AboutSection = () => {
return (
<About>
<Description>
{/*This is the button */}
<Link to="/contact">
<motion.button variants={fade}>
Contact Me
</motion.button>
</Link>
</Description>
<Image>
<motion.img variants={photoAnim} src={homeImg1} alt="camera guy" />
</Image>
<Wave />
</About>
);
};
const Hide = styled.div`
overflow: hidden;
`;
export default AboutSection;
Code of my Nav.js
import React from "react";
import { Link, useHistory } from "react-router-dom";
const Nav = () => {
return (
<StyledNav>
<h1>
<Link id="logo" to="/">
Nitish Poonia
</Link>
</h1>
<ul>
<li>
<Link to="/contact">Contact Me</Link>
</li>
</ul>
</StyledNav>
);
};
export default Nav;
My Contact me
import React from "react";
import styled from "styled-components";
//Animation
import { motion } from "framer-motion";
import { pageAnimation, titleAnim } from "../animation";
const ContactUs = () => {
return (
<ContactStyle>
<Title>
<Hide>
<motion.h2 variants={titleAnim}>Get in touch.</motion.h2>
</Hide>
<div className="line2"></div>
</Title>
<div>
<Hide>
<Social variants={titleAnim}>
<Circle />
<h2>Socials</h2>
</Social>
</Hide>
<Hide>
<Social variants={titleAnim}>
<Circle />
<h2>Send me a message</h2>
</Social>
</Hide>
<Hide>
<Social variants={titleAnim}>
<Circle />
<h2>Drop an email.</h2>
</Social>
</Hide>
</div>
</ContactStyle>
);
};
export default ContactUs;
I think there can be a few changes you can do towards fixing the issues. Noting them down below.
Switch component should not be passed any props, you don't need to get location here using useLocation and pass it there and same for key as well. Refer React Router Switch Link
Can you change the order of your routes to look like something below just to be safe. We are putting the / i.e. the base route at the end, so that it acts as a fallback too.
<BrowserRouter>
<Switch>
<Route path="/work" exact>
<MyWork />
</Route>
<Route path="/contact" exact>
<ContactMe />
</Route>
<Route path="/">
<AboutMe />
</Route>
</Switch>
</BrowserRouter>

Link not re-directing to a page in React

I am trying to make a Navbar but the isn't re-directing to the given page. If I click any of the links in the Navbar, it would change the path in the url bar but won't re-direct to that page. I am not sure if I am missing anything. When I replace it with the tags, it works perfectly.
Navbar.js
import React from "react";
import { BrowserRouter as Router, Link, Switch } from "react-router-dom";
const Navbar = () => {
return (
<Router>
<Switch>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/articles">Articles</Link>
</li>
<li>
<Link to="/articles-all">All articles</Link>
</li>
</ul>
</nav>
</Switch>
</Router>
);
};
export default Navbar;
App.js
import React from "react";
import { BrowserRouter as Router, Route } from "react-router-dom";
import './App.css'
//pages
import Home from "./Pages/Home";
import About from "./Pages/About";
import Articles from "./Pages/Articles";
import ArticlesList from "./Pages/ArticlesList";
//components
import Navbar from './components/Navbar';
const App = () => {
return (
<div>
<Navbar/>
<Navigation />
</div>
);
};
export default App;
const Navigation = () => {
return (
<Router>
<div id="page-body">
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/articles" component={Articles} />
<Route path="/articles-all" component={ArticlesList} />
</div>
</Router>
);
};
Since you define the Router within Navigation and another one in Navbar your Links are not able to communicate to the Router Component in Navigation as they just communicate to their nearest parent Router component
You must you use a single Router instance to be able to perform seemless navigation within your App. Also a Switch component is not needed with Links but with Route
const App = () => {
return (
<Router>
<Router component={Navbar}/> // rendered as default route so that they receive router props
<Router component={Navigation} />
</Router>
);
};
export default App;
const Navigation = () => {
return (
<div id="page-body">
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/articles" component={Articles} />
<Route path="/articles-all" component={ArticlesList} />
</div>
);
};
const Navbar = () => {
return (
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/articles">Articles</Link>
</li>
<li>
<Link to="/articles-all">All articles</Link>
</li>
</ul>
</nav>
);
};
export default Navbar;
Here's a working codesandbox URL https://codesandbox.io/s/frosty-black-3i8hp?file=/src/App.js
You were wrapping links with browserRouter and Switch. These APIs are intended to wrap Routes only.
So, It wasn't able to communicate well with your react app.

Resources