Context Provider is not a Route component error - javascript

I'm getting this error when I wrap some of my routes in a Context Provider tag. I basically need to send the logged user context to each of these routes for them to use or modify. The value sent in the provider is this:
const [loggedUser, setLoggedUser] = useState(null)
const value = useMemo(() => {{ loggedUser, setLoggedUser }}, [loggedUser, setLoggedUser])
And here is the code:
return (
<>
<Routes>
<Route path="/" element={ <MainPage /> } />
<UserContext.Provider value={value}>
<Route path="/login" element={<LoginMenu/>} />
<Route path="/register" element={<RegisterMenu/>} />
<Route path="/dashboard" element={<Dashboard tasks={tasks} />} />
</UserContext.Provider>
</Routes>
</>
)

Only Route component can be a child of a Route component. Abstract the UserContext.Provider component into a layout route.
Example:
import { Routes, Route, Outlet } from 'react-router-dom';
const UserContextProvider = () => (
<UserContext.Provider value={value}>
<Outlet />
</UserContext.Provider>
);
...
<Routes>
<Route path="/" element={<MainPage />} />
<Route element={<UserContextProvider />}>
<Route path="/login" element={<LoginMenu />} />
<Route path="/register" element={<RegisterMenu />} />
<Route path="/dashboard" element={<Dashboard tasks={tasks} />} />
</Route>
</Routes>
Or wrap the entire Routes in the UserContext.Provider component.
Example:
return (
<UserContext.Provider value={value}>
<Routes>
<Route path="/" element={ <MainPage /> } />
<Route path="/login" element={<LoginMenu />} />
<Route path="/register" element={<RegisterMenu />} />
<Route path="/dashboard" element={<Dashboard tasks={tasks} />} />
</Routes>
</UserContext.Provider>
);

Related

Nested Routing in react js. Make default component on user click

<BrowserRouter>
<Routes>
<Route path='/' element={<Home />} />
<Route path='users' element={<Users />} >
<Route path='user1' element={<User1 />} />
<Route path='user2' element={<User2 />} />
<Route path='user3' element={<User3 />} />
</Route>
</Routes>
</BrowserRouter>
____________________________________________
import React from 'react'
import { NavLink, Outlet } from 'react-router-dom'
function Users() {
return (
<div>
<NavLink to='user1'>User1</NavLink>
<NavLink to='user2'>User2</NavLink>
<NavLink to='user3'>User2</NavLink>
<Outlet/>
</div>
)
}
export default Users;
I am using react router dom#6. While hitting users url wanted to make user1 as a default component to show on screen along with users and it also redirects url to users/user1
You can use the <Navigate> element.
<Route path='users' element={<Users />} >
<Route path='' element={<Navigate to="users/user1" replace/>} />
<Route path='user1' element={<User1 />} />
<Route path='user2' element={<User2 />} />
<Route path='user3' element={<User3 />} />
</Route>

How can I arrange my Routes on the App component

I have various routes and I also have some data from context api that I want to pass to certain routes, excluding some. So,
There is the <UserContext.Provider> that should be wrapped inside all the routes.
There is also the <Route element={<PrivateRoute />}> that sould be wrapped inside most of the routes because it should be checking the authenticated user.
And then there are components like <FruitsData> and <WeatherData> that I should only use to wrap <Route path="training" element={<Training />} /> which is inside <Route element={<PrivateRoute />}> and <UserContext.Provider>
So, my question. How can I wrap the component mentioned in no.3 the right way without having to wrap it around all the other components like I have done below?
<UserContext.Provider value={user}>
<WeatherData>
<FruitsData>
<Routes>
<Route element={<PrivateRoute />}>
<Route path="/" element={<Dashboard />} />
<Route path="/test" element={<TestPage />} />
<Route path="training" element={<Training />} />
<Route path="fruit-details/:fruitId" element={<FruitDetails />} />
<Route path="my-farm" element={<MyFarmList />} />
<Route path="add-farm" element={<AddFarm />} />
<Route path="farm-details" element={<FarmDetails />} />
<Route path="add-post" element={<AddPost />} />
<Route path="post-details/:postId" element={<PostDetails />} />
<Route path="infestation-details/:infestationId" element={<InfestationDetails />} />
<Route path="farm-details/:username/:farmId" element={<FarmDetails />} />
<Route path="farm-details/:username/:farmId/fruits" element={<FarmFruits />} />
<Route path="area" element={<Area />} />
<Route path="shop" element={<Shop />} />
<Route path="packages" element={<Packages />} />
<Route path="seedlings" element={<Seedlings />} />
<Route path="profile" element={<Profile />} />
<Route path="product-details/:seedlingId" element={<ProductDetails />} />
<Route path="pricing" element={<Pricing />} />
<Route path="community" element={<Community />} />
<Route path="complete-profile" element={<CompleteProfile />} />
</Route>
<Route path="admin/" element={<AdminPrivateRoute />}>
<Route path="home" element={<Home />} />
<Route path="farmers" element={<Farmers />} />
<Route path="farms" element={<Farms />} />
</Route>
</Routes>
</FruitsData>
</WeatherData>
</UserContext.Provider>
Thank you
I don't see any overt issue with the way all the context providers wrap the entirety of the routes, but if you are trying to limit the scope of any specific provider then the solution here is to have them render an Outlet component instead of the children prop and render them as layout routes.
Example:
const UserLayout = () => {
... logic/state/etc ...
return (
<UserContext.Provider value={user}>
<Outlet />
</UserContext.Provider>
);
};
const FruitesWeatherLayout = () => {
... logic/state/etc ...
return (
<WeatherData>
<FruitsData>
<Outlet />
</FruitsData>
</WeatherData>
);
};
...
<Routes>
<Route element={<UserLayout />}> // <-- layout route
<Route element={<PrivateRoute />}>
<Route path="/" element={<Dashboard />} />
<Route path="/test" element={<TestPage />} />
<Route element={<FruitesWeatherLayout />}> // <-- layout route
<Route path="training" element={<Training />} />
</Route>
<Route path="fruit-details/:fruitId" element={<FruitDetails />} />
<Route path="my-farm" element={<MyFarmList />} />
<Route path="add-farm" element={<AddFarm />} />
<Route path="farm-details" element={<FarmDetails />} />
<Route path="add-post" element={<AddPost />} />
<Route path="post-details/:postId" element={<PostDetails />} />
<Route path="infestation-details/:infestationId" element={<InfestationDetails />} />
<Route path="farm-details/:username/:farmId" element={<FarmDetails />} />
<Route path="farm-details/:username/:farmId/fruits" element={<FarmFruits />} />
<Route path="area" element={<Area />} />
<Route path="shop" element={<Shop />} />
<Route path="packages" element={<Packages />} />
<Route path="seedlings" element={<Seedlings />} />
<Route path="profile" element={<Profile />} />
<Route path="product-details/:seedlingId" element={<ProductDetails />} />
<Route path="pricing" element={<Pricing />} />
<Route path="community" element={<Community />} />
<Route path="complete-profile" element={<CompleteProfile />} />
</Route>
<Route path="admin/" element={<AdminPrivateRoute />}>
<Route path="home" element={<Home />} />
<Route path="farmers" element={<Farmers />} />
<Route path="farms" element={<Farms />} />
</Route>
</Route>
</Routes>

Render error render in error content area

const Pages = () => {
return (
<>
<Box display="flex">
{window.location.pathname === "/profile" ? undefined : <Sidebar />}
<Box flex={3}>
<Navbar />
<Routes>
{/* Content Area */}
<Route exact path="/" element={<Dashboard />} />
<Route exact path="/calendar" element={<Calendar />} />
<Route exact path="/task" element={<div>Task</div>} />
<Route exact path="/projects" element={<div>Projects</div>} />
<Route exact path="/teamMember" element={<div>Team Member</div>} />
<Route exact path="/profile" element={<Profile />} />
{/* Error Path */}
<Route path="*" element={<div>404</div>} />
</Routes>
</Box>
</Box>
</>
);
};enter code here
Hello, where do I put my error path because when it renders, it renders on my content area?
It is because you continually render a layout(Box, Sidebar, Navbar). There are a few options in order to achieve your request you have to either:
create a Layout component that will render Box, Sidebar, and Navbar inside and use that Layout inside your pages, for example:
const Dashboard = () => {
// ...
return (
<Layout>
Dashboard content
</Layout>
)
}
or use the benefit of the new latest react-router package:
import { Outlet } from 'react-router-dom'
const Layout = () => {
return (
<Box display="flex">
{window.location.pathname === "/profile" ? undefined : <Sidebar />}
<Box flex={3}>
<Navbar />
<Outlet /> {/* Roughly speaking this is `children`. Refer to the documentation */}
</Box>
)
}
<Routes>
<Route element={<Layout />} path="/">
<Route index element={<Dashboard />} />
<Route path="/calendar" element={<Calendar />} />
<Route path="/task" element={<div>Task</div>} />
<Route path="/projects" element={<div>Projects</div>} />
<Route path="/teamMember" element={<div>Team Member</div>} />
<Route path="/profile" element={<Profile />} />
</Route>
<Route path="*" element={<div>404</div>} />
</Routes>

How to do non-existent routes redirect to homepage in react router dom?

I would like all routes other than those registered below to direct me to the main page.
example:
testexample.com/contact
-> Returns me to the contact page
testexample.com/sdlskdsd
-> Route does not exist, return to main page
import {
BrowserRouter,
Routes,
Route
} from 'react-router-dom'
import Footerpage from './components/footerpage/Footerpage';
import Navegation from './components/navegation/Navegation';
import Homepage from './pages/Homepage';
import Contact from './pages/contact/Contact';
import Bookpage from './pages/bookpage/Bookpage';
import Success from './pages/contact/status/Success';
import Error from './pages/contact/status/Error';
function App() {
return (
<BrowserRouter>
<Navegation />
<Routes>
<Route path='/' exact element={<Homepage />} />
<Route path='/contact' exact element={<Contact />} />
<Route path='/contactsuccess' exact element={<Success />} />
<Route path='/contacterr' exact element={<Error />} />
<Route path='/bookpage' exact element={<Bookpage />} />
</Routes>
<Footerpage />
</BrowserRouter>
);
}
export default App;
Redirect unknown/unhandled routes to the "/" path with the Navigate component.
<Route path="*" element={<Navigate to="/" replace />} />
Also, in RRDv6 all routes are now always exactly matched, there is no longer any exact prop, so these should all be removed.
Full routes example:
import {
BrowserRouter,
Routes,
Route,
Navigate
} from 'react-router-dom';
...
<Routes>
<Route path='/' element={<Homepage />} />
<Route path='/contact' element={<Contact />} />
<Route path='/contactsuccess' element={<Success />} />
<Route path='/contacterr' element={<Error />} />
<Route path='/bookpage' element={<Bookpage />} />
<Route path="*" element={<Navigate to="/" replace />} /> // <-- redirect
</Routes>
Add a default route
import {
BrowserRouter,
Routes,
Route
} from 'react-router-dom'
import Footerpage from './components/footerpage/Footerpage';
import Navegation from './components/navegation/Navegation';
import Homepage from './pages/Homepage';
import Contact from './pages/contact/Contact';
import Bookpage from './pages/bookpage/Bookpage';
import Success from './pages/contact/status/Success';
import Error from './pages/contact/status/Error';
function App() {
return (
<BrowserRouter>
<Navegation />
<Routes>
<Route path='/' exact element={<Homepage />} />
<Route path='/contact' exact element={<Contact />} />
<Route path='/contactsuccess' exact element={<Success />} />
<Route path='/contacterr' exact element={<Error />} />
<Route path='/bookpage' exact element={<Bookpage />} />
<Route element={<Homepage />} />
</Routes>
<Footerpage />
</BrowserRouter>
);
}
export default App;
Another way of doing it
<Routes>
<Route path='/' exact element={<Homepage />} />
<Route path='/contact' exact element={<Contact />} />
<Route path='/contactsuccess' exact element={<Success />} />
<Route path='/contacterr' exact element={<Error />} />
<Route path='/bookpage' exact element={<Bookpage />} />
<Route path='/*' element={<Homepage />} />
</Routes>

React router v5 : 3rd level of nesting is not recognising path

I am creating an app which requires multiple level of nesting. from 3rd level my routes are not getting recognised.
App JS
const App = () => {
return (
<React.Fragment>
<Router>
<Switch>
<Route path="/login">
<Login />
</Route>
<Route path="/">
<Home />
</Route>
</Switch>
</Router>
</React.Fragment>
);
};
Home JS
export default class Home extends React.Component {
render() {
return (
<React.Fragment>
<Header />
<ContentNav />
<Switch>
<Route path="/clients">
<Clients />
</Route>
<Route path="/publishers">
<Publishers />
</Route>
<Route path="/">
<Redirect to="/clients" />
</Route>
</Switch>
</React.Fragment>
);
}
}
Clients JS
class Clients extends React.Component {
render() {
return (
<React.Fragment>
Clients Page
<Switch>
<Route path="/add">
<AddClient />
</Route>
<Route path="/edit">
<AddClient />
</Route>
<Route path="/">
<Entity />
</Route>
</Switch>
</React.Fragment>
);
}
}
these routers are rendering same component
http://localhost:3000/clients
http://localhost:3000/clients/add
http://localhost:3000/clients/edit
react nested urls are not relative, have to specify absolute path :
<Switch>
<Route path="clients/add">
<AddClient />
</Route>
<Route path="clients/edit">
<AddClient />
</Route>
<Route path="clients/">
<Entity />
</Route>
</Switch>

Categories

Resources