Please help me
When the Route is not inside <Routes> it gives an error:
Error: A is only ever to be used as the child of element, never rendered directly. Please wrap your in a
When it is inside <Routes> it give an error as:
Error: [Abc] is not a <Route> component. All component children of must be a <Route> or <React.Fragment>
Pls help me to resolve this situation? Or any suggestion.
Tried this but one of the above error in both cases.
As this does not generate an error, however my child component of the private route does not render.
import React from 'react'
import './App.css'
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Header from './components/Header'
import Home from './components/Home'
import Login from './components/Login'
import ProtectedRoute from './components/Helper/ProtectedRoute';
import { UserStorage } from './UserContext';
import User from './components/User';
const App = () => {
return (
<div>
<BrowserRouter>
<UserStorage>
<>
<Header />
<Routes>
<Route path="/" element={<Home />} />
<Route path="login/*" element={<Login />} />
<Route path='/conta' element={<ProtectedRoute/>}>
<Route path='/conta' element={<User/>}/>
</Route>
</Routes>
</>
</UserStorage>
</BrowserRouter>
</div>
)
}
export default App;
ProtectedRoute
import React from 'react';
import { UserContext } from '../../UserContext';
import {Routes, Route, Navigate } from 'react-router-dom';
const ProtectedRoute = (props) => {
const { login } = React.useContext(UserContext);
if (login === true) return (
<Routes>
<Route {...props} />
</Routes>
);
else if (login === false) return <Navigate to="/login" />;
else return null;
};
export default ProtectedRoute;
With layout wrapper components like ProtectedRoute that renders nested Route components then you need to ensure it is rendering an Outlet for them to be rendered into.
Outlet
import React from 'react';
import { UserContext } from '../../UserContext';
import {Routes, Route, Navigate } from 'react-router-dom';
const ProtectedRoute = () => {
const { login } = React.useContext(UserContext);
if (login === undefined) return null;
return login
? <Outlet /> // <-- nested Route components rendered here
: <Navigate to="/login" replace />;
};
...
<Route path='/conta' element={<ProtectedRoute/>}>
<Route path='/conta' element={<User/>}/> // <-- rendered into outlet
</Route>
Related
Inside App.js:
import React, { useState } from 'react';
import './App.css';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import Dashboard from './components/Dashboard/Dashboard';
import Preferences from './components/Preferences/Preferences';
import Login from './components/Login/Login';
function App() {
const [token, setToken] = useState();
if(!token) {
return <Login setToken={setToken} />
}
return (
<div className="wrapper">
<h1>Application</h1>
<BrowserRouter>
<Routes>
/*<Route path="/dashboard">*/
<Route path="/dashboard" element={<Dashboard/>} /></Route>
/*<Route path="/preferences">*/
<Route path="/preferences" element={<Preferences/>} /></Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;`
Inside Dashboard.js (../src/components/Dashboard/Dashboard.js):
import React from 'react';
export default function Dashboard() {
return(
<h2>Dashboard</h2>
);
}
Url: http://localhost:3000/dashboard
I want to see the Dashboard content along with the App page content (Application and Dashboard headers) when I load the browser. But when I load the browser, it only displays the App page content and getting the same error:
"Matched leaf route at location "/dashboard" does not have an element. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page."
You are using Routes instead of Router. Replace it on your line 3 and in the return().
Source: React-router https://v5.reactrouter.com/web/api/Route
//...
import { BrowserRouter, Route, Router } from 'react-router-dom';
//...
return ( ...
<Router>
/*<Route path="/dashboard">*/
<Route path="/dashboard" element={<Dashboard/>} />
/*<Route path="/preferences">*/
<Route path="/preferences" element={<Preferences/>} />
</Router>
...)
export default App;
Please specify which version of React router you are using, since a lot of the functionality has changed, is it 6.4 or is still 5 ?
Either way, please remove the comments of the routes, I don't think they help at all.
if you have chosen BrowserRouter from the 6.4 version then it should be used like this
import { BrowserRouter, Route } from 'react-router-dom';
return (
<BrowserRouter>
<Route path="/" element={<RootComp />} >
<Route path="dashboard" element={<Dashboard/>} />
<Route path="preferences" element={<Preferences/>} />
</Route>
</BrowserRouter>
)
export default App;
Where <RootComp /> should have an <Outlet /> as children
import { Outlet } from 'react-router-dom';
const RootComp = () => {
return <div><Outlet /></div>
}
export default RootComp;
Again, this is for the latest React Router component, however, I would advise using createBrowserRouter() rather than the old component-based trees, this way you can programatically create and manage the routes in an Object.
This question already has answers here:
Error: [PrivateRoute] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
(18 answers)
How to create a protected route with react-router-dom?
(5 answers)
Closed 8 months ago.
This post was edited and submitted for review 8 months ago and failed to reopen the post:
Original close reason(s) were not resolved
I'm using react router dom v6, and trying to follow a tutorial which uses v5.
my error is Uncaught Error: [ProtectedRoute] is not a component.All component children of must be a or <React.Fragment>
This is my protectedRoute.js, I replaced Redirect with Navigate
import React, { Fragment } from "react";
import { useSelector } from "react-redux";
import { Navigate, Route } from "react-router-dom";
const ProtectedRoute = ({ isAdmin, component: Component, ...rest }) => {
const { loading, isAuthenticated, user } = useSelector((state) => state.user);
return (
<Fragment>
{loading === false && (
<Route
{...rest}
render={(props) => {
if (isAuthenticated === false) {
return <Navigate to="/login" />;
}
if (isAdmin === true && user.role !== "admin") {
return <Navigate to="/login" />;
}
return <Component {...props} />;
}}
/>
)}
</Fragment>
);
};
export default ProtectedRoute;
and this is my app.js, i'm using element instead of component, I dont know where should I change that in the ProtectedRoute.js
import './App.css';
import Header from "./components/layout/Header/Header"
import {BrowserRouter as Router, Route, Routes} from 'react-router-dom'
import React from "react";
import WebFont from 'webfontloader';
import Footer from "./components/layout/Footer/Footer"
import Home from "./components/Home/Home";
import ProductDetails from "./components/Product/ProductDetails"
import Products from "./components/Product/Products"
import Search from "./components/Product/Search"
import LoginSignUp from './components/User/LoginSignUp';
import store from "./store"
import { loadUser } from './actions/userAction';
import UserOptions from "./components/layout/Header/UserOptions"
import { useSelector } from 'react-redux';
import Profile from "./components/User/Profile"
import ProtectedRoute from './components/Route/ProtectedRoute';
function App() {
const {isAuthenticated, user} = useSelector(state=>state.user)
React.useEffect(() => {
WebFont.load({
google:{
families: [ "Droid Sans", "Chilanka"],
},
});
store.dispatch(loadUser())
}, []);
return (
<Router>
<Header/>
{isAuthenticated && <UserOptions user={user} />}
<Routes>
<Route exact path="/" element={<Home/>}/>
<Route exact path="/product/:id" element={<ProductDetails/>}/>
<Route exact path="/products" element={<Products/>}/>
<Route path="/products/:keyword" element={<Products/>}/>
<Route exact path="/search" element={<Search/>}/>
<ProtectedRoute exact path="/account" element={<Profile/>}/>
<Route exact path="/login" element={<LoginSignUp/>}/>
</Routes>
<Footer/>
</Router>
);
}
export default App;
I am doing a personal React.js project. I am trying to use react-router-dom, but I haven't been able to make it work. I did the BrowserRouter in the App.js. Till there the app works fine, but I cannot make the routing redirect dynamically to a map item. I tried to follow the documentation and some tutorials unsuccesfully. The data comes from the Star Wars API This is the code:
App.js:
import './App.css';
import { Route, BrowserRouter as Router, Routes } from "react-router-dom";
import Home from './components/Home';
import MovieDetail from './components/MovieDetail'
import Navbar from './components/Navbar';
function App() {
return (
<Router>
<>
<Navbar />
<Routes>
<Route exact path='/' element={<Home />} />
</Routes>
<Routes>
<Route exact path to='/:movieId' element={<MovieDetail />} />
</Routes>
</>
</Router>
);
}
export default App;
ItemDetail:
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
const MovieDetail = () => {
const { movieId } = useParams();
const [result, setResult] = useState([]);
const fetchData = async () => {
const res = await fetch("https://www.swapi.tech/api/films/");
const json = await res.json();
setResult(json.result);
}
useEffect(() => {
fetchData();
}, []);
let movieMatch = (result.find(value) => value.properties.title == movieId)
return (
<div>
<h2>
{result
.find((value) => {value.properties.title == movieId})}
</h2>
</div>
);
}
export default MovieDetail;
UPDATE
This is a link to the whole code in codesand with updated App.js
From your code I'm assuming you're using React Router v6 in your project. Try the below code:
import './App.css';
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from './components/Home';
import MovieDetail from './components/MovieDetail'
import Navbar from './components/Navbar';
function App() {
return (
<BrowserRouter>
<Routes>
<Navbar />
<Route path='/' element={<Home />} />
<Route path=':movieId' element={<MovieDetail />} />
</Routes>
</BrowserRouter>
);
}
export default App;
Checkout React Router's Documentation for more detail.
if you are using index.js as a wrapper for app.js <BrowserRouter /> or <Router /> in your case is not used in app.js it's used in index.js otherwise it will not work
index.js should look like this : -
import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
function App() {
return <h1>Hello React Router</h1>;
}
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root")
);
**For example just Let's say you are having "/movies" route and you want when ever your app (route = "/") starts / loads up to be redirected to "/movies" **
then wrap the routing logic with *<Switch />* ,make use of Redirect property of router dom to redirect from "/" to "/movies" and use component instead of element to render the corresponding component plus dont wrap with <Routes> </Routes> every time you are doing the route as we used it in index.js
then app.js will be : -
import './App.css';
import { Route, BrowserRouter as Router, Routes } from "react-router-dom";
import Home from './components/Home';
import MovieDetail from './components/MovieDetail'
import Navbar from './components/Navbar';
function App() {
return (
<>
<Navbar />
<Switch>
<Route exact path='/movies' component={<Home />} />
<Route exact path to='movies/:movieId' component={<MovieDetail />}
// to redirect from "/" to "/movies"
<Redirect from="/" to="/students"></Redirect>
);
}
Protected Routes.js:
In protected routes you can see I'm using directly false in if statement but I'm still able to see that page why?
import React from 'react';
import { Route } from 'react-router-dom';
// import Auth from './User/Auth';
import Error401 from './Error/401';
// create a component for protected route
console.log('Routes.js');
export const ProtectedRoute = ({ element: Element, ...rest }) => {
console.log("Function Called")
return (
<Route {...rest} render={props => {
if(false){
return <Element {...props} />
}else{
return <Error401 />
}
}
} />
)
}
App.js:
This is app.js where I'm using protected routes component
import './App.css';
import React from 'react';
import { BrowserRouter, Route, Routes } from 'react-router-dom';
import { Layout } from 'antd';
import { MoneyCollectOutlined } from '#ant-design/icons';
import Login from './Components/User/Login';
import Signup from './Components/User/Signup';
import {ProtectedRoute} from './Components/Routes';
import Error404 from './Components/Error/404';
function App() {
return (
<BrowserRouter>
<Layout style={{minHeight:"100vh"}}>
<Layout.Header>
<h1 style={{color:"white"}} align="center"> <MoneyCollectOutlined/>MoneyG</h1>
</Layout.Header>
<Layout.Content style={{minHeight:"100%"}}>
<Routes>
<ProtectedRoute exact path="/register" element={<Signup/>} />
<ProtectedRoute exact path="/login" element={<Login/>} />
<Route path="*" element={<Error404/>} />
</Routes>
</Layout.Content>
</Layout>
</BrowserRouter>
);
}
export default App;
First, <Routes> elements should only have <Route> elements as children. You should move your protection logic down a layer.
Secondly, the render prop doesn't exist anymore in V6. It was replaced in favor of element. See doc.
Here is how you might tackle it:
<Routes>
<Route exact path="/register" element={(
<ProtectedRoute>
<Signup/>
</ProtectedRoute>
)} />
<Route exact path="/login" element={(
<ProtectedRoute>
<Login/>
</ProtectedRoute>
)} />
<Route path="*" element={<Error404/>} />
</Routes>
And:
const ProtectedRoute = () => {
if (condition) { return <Error401 />; } // You might as well use Navigate here
return children;
};
you can use createContext & useContext
//store/AuthApi.jsx
import { createContext } from "react";
const AuthApi = createContext();
export default AuthApi;
Then define the context app.jsx
import React, from 'react'
import { AllRoutes } from 'routes/Routes';
import { BrowserRouter as Router } from "react-router-dom";
import AuthApi from 'store/AuthApi';
const App = () => {
const [user, setUser] = useState(false);
useEffect(() => {
// you can get user from localStorage or Cookie(js-cookie npm)
//then you can change user state true or false
}, [])
return (
<>
<AuthApi.Provider value={{ user, setUser }}>
<Router>
<AllRoutes />
</Router>
</AuthApi.Provider>
<Toast />
</>
)
}
export default App
then see AllRoutes
//routes/Routes
import React, { useContext } from "react";
import { Routes, Route } from "react-router-dom";
import { SignIn, SignUp, Dashboard } from "pages";
import AuthApi from "store/AuthApi";
export const ProtectedRouting = () => {
return (
<Routes >
<Route path='/' exact element={<Dashboard />} />
// add more protected routes
</Routes>
)
}
export const AuthRouting = () => {
return (
<Routes >
<Route exact={true} path='/sign-in' element={<SignIn />} />
<Route exact={true} path='/sign-up' element={<SignUp />} />
</Routes>
)
}
export const AllRoutes = ()=> {
const context = useContext(AuthApi);
console.log(context.user)
return (
context.user ?
<ProtectedRouting />
: <AuthRouting />
)
}
pages/SignIn.jsx
import React,{ useContext } from 'react';
import AuthApi from "store/AuthApi";
const SignIn = () => {
const context = useContext(AuthApi);
const signInSubmit =(e)=> {
e.preventDefault();
//post request to signin
// if login is successfull then save user or token in cookie or localStorage or something
context?.setUser(true);
//...
}
return (
//signin code here
<form onSubmit={signInSubmit}>
///input here
</form>
)
}
export default SignIn
I am using private route in my app to access dashboard. if I am not logged in it worked correctly and redirect me to the sign in page. but even if I am logged in it does not gives access to dashboard. Here is my code.
App.js
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import Home from './containers/Home';
import Login from './containers/Login';
import Dashboard from './containers/Dashboard';
import PrivateRoute from './components/PrivateRoute';
import { Provider } from 'react-redux';
import store from './store';
const App = () => (
<Provider store={store}>
<Router>
<Layout>
<Switch>
<Route exact path='/' component={Home} />
<PrivateRoute exact path='/dashboard' component={Dashboard} />
<Route exact path='/login' component={Login} />
</Switch>
</Layout>
</Router>
</Provider>
);
export default App;
PrivateRoute.js
import React from 'react';
import { Route, Redirect } from 'react-router-dom';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
const PrivateRoute = ({ component: Component, auth, ...rest }) => (
<Route
{...rest}
render={(props) => {
if (!auth.isAuthenticated) {
return <Redirect to="/login" />;
} else {
return <Component {...props} />;
}
}}
/>
);
const mapStateToProps = (state) => ({
auth: state.auth,
});
export default connect(mapStateToProps)(PrivateRoute);
And if I am logged in on react redux tool my states are these
I noticed even if isAuthanticated becomes true after login but else part of privateRoutes.js never called