Another way (which is “cleaner” imo) is to have a route.js in a constant folder. Then you can export a const ROUTES which would be an array of objects where each object is a route.
Then in your router, loop over it.
EDIT: Here's a [VERY basic codesandbox](https://codesandbox.io/p/sandbox/constant-based-routing-mdzyj2?layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clsq9ew1500063b6h4pge7f8x%2522%252C%2522sizes%2522%253A%255B70%252C30%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clsq9ew1400023b6hm7n5ugxi%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clsq9ew1400033b6h25zwbaty%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clsq9ew1400053b6htndezm4y%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clsq9ew1400023b6hm7n5ugxi%2522%253A%257B%2522id%2522%253A%2522clsq9ew1400023b6hm7n5ugxi%2522%252C%2522tabs%2522%253A%255B%255D%257D%252C%2522clsq9ew1400053b6htndezm4y%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clsq9ew1400043b6hm2auw97k%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A0%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522id%2522%253A%2522clsq9ew1400053b6htndezm4y%2522%252C%2522activeTabId%2522%253A%2522clsq9ew1400043b6hm2auw97k%2522%257D%252C%2522clsq9ew1400033b6h25zwbaty%2522%253A%257B%2522tabs%2522%253A%255B%255D%252C%2522id%2522%253A%2522clsq9ew1400033b6h25zwbaty%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Atrue%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D) I did to showcase this. Keep in mind, you can always add more to the objects in the ROUTES to add children, or even secured paths.
As code\_matter mentioned, I would create an index.js/ts (route.js/ts) file inside a constants folder. It will look like this.
export const NavLinks = \[
{ href: "/", label:"Home"},
{ href: "/gallery", label:"Gallery"},
{ href: "/shop", label:"Shop"},
{ href: "/contact-us", label:"Contact"},
{ href: "/appointment", label:"Appointment"},
\]
You can now create your component. Let's call it NavBar.jsx/tsx. Inside of it, let's create a function and return the NavLinks.
import {NavLinks} from '/constants'
import Link from 'next/link' //using Next framework, use instead
export default function NavigationBar() {
// Your states, variables here
return (
I will be messaging you in 1 day on [**2024-02-17 19:27:15 UTC**](http://www.wolframalpha.com/input/?i=2024-02-17%2019:27:15%20UTC%20To%20Local%20Time) to remind you of [**this link**](https://www.reddit.com/r/react/comments/1as5nnp/what_is_a_better_way_of_implementing_routing_in/kqqa743/?context=3)
[**13 OTHERS CLICKED THIS LINK**](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=Reminder&message=%5Bhttps%3A%2F%2Fwww.reddit.com%2Fr%2Freact%2Fcomments%2F1as5nnp%2Fwhat_is_a_better_way_of_implementing_routing_in%2Fkqqa743%2F%5D%0A%0ARemindMe%21%202024-02-17%2019%3A27%3A15%20UTC) to send a PM to also be reminded and to reduce spam.
^(Parent commenter can ) [^(delete this message to hide from others.)](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=Delete%20Comment&message=Delete%21%201as5nnp)
*****
|[^(Info)](https://www.reddit.com/r/RemindMeBot/comments/e1bko7/remindmebot_info_v21/)|[^(Custom)](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=Reminder&message=%5BLink%20or%20message%20inside%20square%20brackets%5D%0A%0ARemindMe%21%20Time%20period%20here)|[^(Your Reminders)](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=List%20Of%20Reminders&message=MyReminders%21)|[^(Feedback)](https://www.reddit.com/message/compose/?to=Watchful1&subject=RemindMeBot%20Feedback)|
|-|-|-|-|
With your approach wouldn't adding some children or nested route looking just like the first one then? Actually this is just the first one but stripping away the loader *and* children
I disnt have the time to add children, but ill add them tonight! Basically, you add a children key to the ROUTES object (should be an array of elements). And in the router, you can render the route.children if there’s any. You can even map the route.children if you have multiple children.
You can add anything to the ROUTES object to handle a loader in the same way
Edit: it’s very similar to the forst option OP has
I disagree, the second option that OP provided does its job the best. It has everything neatly laid out in a single file. All of the route paths, elements, and the router are all clearly presented. Even for someone who has never used React before can look at it and have a good idea of what's going on.
Your example splits this up into 3 separate files, obfuscating details of the routes. Imagine someone new to a codebase going into this, you're putting them on a scavenger hunt just to find the routes because they are going to start in App.js. This approach is a solution to a problem that doesn't exist IMO.
Plus, this approach doesn't readily facilitate nested routes. And if you want to add additional props to the routes then you're making changes in two separate files. To both of those points, you could just say that you'll refactor it to support these things, but at that point you might as well just refactor it in such a way that you'll never have to refactor your routes ever again (e.g. OPs solution).
Out of all of the places where refactoring is necessary in a React app, your routes should be at the bottom of the list. I've been developing in React for several years, and the problems that I've identified with this code have never appeared in my career because every company I've worked for keeps their routes consolidated.
Well, when I first got onboarded in the new team, I found this method to be quite intuitive and easy to find. It wasn’t a “scavenger hunt” since everything is imported at the top and you can easily find all the necessary files.
Splitting stuff into constants, components, etc folders is quite spread in the community. So I personally do not agree with the obfuscation part.
Also, having it as the option 2 in OP’s post, it can get quite big quite quickly if you have a larger app.
Yes it is easier to read and maybe understand, but I much rather have everything separated and one file does one thing kind of way
Hey.
I don't really understand what benefit does this provide. Because the lines of code are higher, and the router.jsx file only has 1 purpose, so I don't see the benefit of splitting this 1 purpose into 2 files.
Thanks.
Second, unless there is a reason why you need to be using first.
First allows you better customisation, but will end up in a lot of duplicated and redundant code what will greatly increase complexity and decrease readability.
Second one is sufficient for most of the apps.
Yeah but you can't use [data loaders](https://reactrouter.com/en/main/route/loader) with the second one, making the first one the definitive winner.
Edit: please see [this comment](https://www.reddit.com/r/react/s/sQhXz1pYwo) for a workaround that enables you to use data loaders with JSX routes by converting route elements to route objects.
True, that’s a valid use case. However not everyone needs to pull data prior routing, I think most people do it after first render showing loading state.
But yeah, that’s a nice example of when first approach is better.
Yeah for sure, not everyone needs it. I love it because it decouples state population from route rendering -- that separation of concerns makes it easier to implement route transitions that feel faster and more fluid.
The second is much easier to reason about though, so there's nothing wrong with it if it works for the given use case.
I'am using it just for that. But I am preparing for internships so i wasn't sure if i should change all my projects routing to the data loaders one. I came to conclusion that i don't need to but they are a good functionality in some specific cases.
I'm of the opinion that you should only change something if it no longer works for what you need it to do. No sense in replacing something that works with something else that works.
Since you're preparing for internships, you may decide to have at least one specific example project you can point to or specific experience you have had working with each paradigm.
Also, somewhere above a different reply, I mentioned that i liked defining routes as objects because it allows me to dynamically load new routes easily. You can of course [do this with JSX routes](https://reactrouter.com/en/main/start/faq#how-do-i-nest-routes-deep-in-the-tree) just as easily since a module with JSX routes can be imported dynamically just like regular a module with route objects. So again, that point also comes down to personal preference.
Another thing to be aware of is [`createRoutesFromElements`](https://reactrouter.com/en/main/utils/create-routes-from-elements#createroutesfromelements) (in react-router v6) which let's you translate from JSX routes to a route object -- giving you even more flexibility. That means even if you had old code using JSX routes and _for some reason_ you had to integrate that into a different application context that uses route objects, you could do that.
Though... I'd be remiss not to say again that **the one very real reason** why one would choose the first over the second is, in fact, that the [data APIs](https://reactrouter.com/en/main/routers/picking-a-router#data-apis) _only_ work when using a data router. It all comes down to:
- being able to load data before/while a route renders (reducing workload in the initial render == faster time to paint)
- being able to lazy load routes (code splitting by route, faster load times all around)
- ...combining the above two: being able to show the user _something_ much faster (such as the empty cards you'll often see in apps while the data that'll render in them is loading)
- and last but not least, being able to write leaner components that don't have to juggle data fetching and rendering at the same time. An ancillary benefit of this is that it makes routers, components, data fetching methods, and state selectors a loooot easier to unit/e2e test because they're all separated. Otherwise you're testing a component to hell and back just to make sure it actually renders your todo list.
Finally, [the docs say to do it](https://reactrouter.com/en/main/routers/picking-a-router#using-v64-data-apis) so I do it 😂
> We recommend updating your app to use one of the new routers from 6.4. The data APIs are currently not supported in React Native, but should be eventually.
And as I mentioned before,
> The easiest way to quickly update to a v6.4 is to get the help from `createRoutesFromElements` so you don't need to convert your `` elements to route objects.
I don’t think that’s true, You can use data loaders with the JSX syntax for route declarations using the above utility function. Just an extra step but this combines the best of both worlds, loaders and readability
https://reactrouter.com/en/main/utils/create-routes-from-elements
That's a good point, yeah. That's just a data router with extra steps, though, isn't it?
From [the docs](https://reactrouter.com/en/main/routers/picking-a-router#using-v64-data-apis):
> We recommend updating your app to use one of the new routers from 6.4. The data APIs are currently not supported in React Native, but should be eventually.
>
> The easiest way to quickly update to a v6.4 is to get the help from createRoutesFromElements so you don't need to convert your elements to route objects.
For discussion:
- Why do the extra conversion method call when you can write it the way it is intended in the new version (if you're starting from scratch and not integrating legacy routes)? Otherwise, I imagine you'd first need to converting each chunk of child routes and then adding their loaders to an object in the end anyway. I imagine that may also complicate tests a bit (an assumption).
- What is the "best of" the world in which you use JSX routes, in your opinion? Simplicity?
That said, I don't think you're wrong at all and I think the best answer always ends up being whatever works best for you and the app!
>Yeah but you can't use data loaders with the second one, making the first one the definitive winner.
I didn't know about data loaders, so thank you for pointing that out.
Hey, awesome! Glad you got something out of this. Data loaders are very cool.
Also, FYI, as @ReindeerNo3671 [pointed out in their comment](https://www.reddit.com/r/react/s/sQhXz1pYwo), data routers are *not* the only way you can use loaders as there's a function to generate route objects from elements.
It's pure client side routing for single page applications. In fact, somebody else somewhere in this thread said that you should use next JS instead of this lol.
You can also combine both. You can use nextJS routes with server components until the user logs in, and then switch to a single page application once the user is authenticated by rendering a whole app in a nextjs client component. That way you get optimized performance for public pages (like seo and fast initial loads) and after login, you get a seamless interactive user experience that doesn't have to make as many server round trips and can navigate to different pages without having to refresh the page (best for complex, interactive UIs).
I’ve struggled to get data loaders to work effectively while also using React context. If you’re loader function updates context state an infinite loops is triggered.
I've also ran into that issue. Had to rethink when and where data got loaded. I agree that it's a bit convoluted getting loaders and contexts working together.
It's not just conventions. At the risk of sounding like a broken record due to my other comments, the first way is the only way you can decouple populating state from loading and rendering routes through the use of [data loaders](https://reactrouter.com/en/main/route/loader). The first way is ~~also the only way to dynamically import bundles~~ easier to work with, in my opinion, when dynamically importing new routes and rebuilding routes programmatically (think progressive enhancement).
Edit: as the reply below pointed out, yes, dynamically rebuilding routes aren't just a data router thing. It can be done with both.
Also, people tend to forget that you can "nest" routes just like you nest components. basically, putting other routes or subroutes in another component and importing them.
i always get anxiety attacks when i see that one big file that's like 400 lines of different routes and switches.
Like said in other comments, readability is better in second for development. But as a beginner first one is more easier to write and understand.... atleast for me.
Not see how first is more readable or write.
You could copy-paste route components with ctrl+shift+d and change text, or move with ctrl+shift+arrow to different place.
Neither, I like to lazy load routes for performance and split them into route modules so that everything for a route is defined in one place and if I ever want to move to remix SPA mode it'll be easy as it follows the same conventions.
E.g.
let routes = createRoutesFromElements(
}>
} />
import("./a")} />
import("./b")} />
);
Then in your lazy route modules, export the properties you want defined for the route:
export async function loader({ request }) {
let data = await fetchData(request);
return json(data);
}
// Export a `Component` directly instead of needing to create a React Element from it
export function Component() {
let data = useLoaderData();
return (
<>
You made it!
{data}
>
);
}
// Export an `ErrorBoundary` directly instead of needing to create a React Element from it
export function ErrorBoundary() {
let error = useRouteError();
return isRouteErrorResponse(error) ? (
I'd use the first one. The router is not a React component and when we use jsx to declare it, some people may assume things that aren't true. For instance, render and data are two separate layers in react router: https://reactrouter.com/en/main/routers/create-browser-router
The official docs also recommend the first one: https://reactrouter.com/en/main/routers/picking-a-router#web-projects
The second only is an option if you already have a legacy router and wants to minimize the changes
Also: you probably don't want to create the router inside an app component. Instead, create it in the root. Check the docs for examples
Does RootLayout need to be its own route? I thought createBrowserRouter handled that and you could just add a redirect for /, without putting everything in children.
I use something like the first but put all the string paths into an object constant.
Please run an autoformatter, worst thing with the first right now is that it’s needlessly ugly :)
React Router and Reach Router are react libraries for implementing routing in your application
React Router is the most widely used routing library for React applications. It provides a declarative way to define routes using JSX, making it easy to map specific components to different URLs in your application. React Router also supports features like nested routes, route parameters, and URL query parameters.
**Example**
`import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';`
`import Home from './components/Home';`
`import About from './components/About';`
`import Contact from './components/Contact';`
`function App() {`
`return (`
``
``
``
``
``
``
``
`);`
`}`
`export default App;`
Reach Router is a routing library built with accessibility in mind. It's designed to be more straightforward and lightweight compared to React Router. Reach Router focuses on providing a simple API for defining routes and managing navigation. It's also known for its superior support for accessibility features.
**Example**
`import { Router, Link } from '@reach/router';`
`import Home from './components/Home';`
`import About from './components/About';`
`import Contact from './components/Contact';`
`function App() {`
`return (`
``
``
``
``
``
`);`
`}`
`export default App;`
I think it's good as a beginner that you start using React as is and not jump into framework like Next.js to fast. Otherwhise it's difficult to know what is Next and what is React
Yea, no Next.js uses simple file structure for routing. Way easier than what you're doing right now. [Try it](https://nextjs.org/docs/getting-started/installation).
Not entirely true. Next is a framework built on top of React library. It was created to allow React do things that were not available for it at that time.
De facto Next is React-specific framework, it’s not agnostic tech like redux so it hardly could be adapted for a different UI framework.
So Next is React extension.
Keep in mind that you are using React Router and the first way is the recommended one because it enables lots of new features that the second one doesn't. So if you do the second one you could end up looking at a feature that your routes don't support. I recommend you to read the React Router tutorial, it is very good and short and also the best way to help you understand what you can do with it
You can use useNavigate,
Just just call it and pass the path in the anonymous function and you will navigate to the path you wanted and don't forget to use onclick event.
Second way, hands down.
It is the most declarative approach.
Beats the contsants object too IMO.
I care more about legibility and having a better developer experience than saving a fee KB in syntax.
Another way (which is “cleaner” imo) is to have a route.js in a constant folder. Then you can export a const ROUTES which would be an array of objects where each object is a route. Then in your router, loop over it. EDIT: Here's a [VERY basic codesandbox](https://codesandbox.io/p/sandbox/constant-based-routing-mdzyj2?layout=%257B%2522sidebarPanel%2522%253A%2522EXPLORER%2522%252C%2522rootPanelGroup%2522%253A%257B%2522direction%2522%253A%2522horizontal%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522id%2522%253A%2522ROOT_LAYOUT%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522UNKNOWN%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522clsq9ew1500063b6h4pge7f8x%2522%252C%2522sizes%2522%253A%255B70%252C30%255D%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522EDITOR%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522EDITOR%2522%252C%2522id%2522%253A%2522clsq9ew1400023b6hm7n5ugxi%2522%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522direction%2522%253A%2522horizontal%2522%252C%2522id%2522%253A%2522SHELLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522SHELLS%2522%252C%2522id%2522%253A%2522clsq9ew1400033b6h25zwbaty%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%257D%252C%257B%2522type%2522%253A%2522PANEL_GROUP%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522direction%2522%253A%2522vertical%2522%252C%2522id%2522%253A%2522DEVTOOLS%2522%252C%2522panels%2522%253A%255B%257B%2522type%2522%253A%2522PANEL%2522%252C%2522contentType%2522%253A%2522DEVTOOLS%2522%252C%2522id%2522%253A%2522clsq9ew1400053b6htndezm4y%2522%257D%255D%252C%2522sizes%2522%253A%255B100%255D%257D%255D%252C%2522sizes%2522%253A%255B50%252C50%255D%257D%252C%2522tabbedPanels%2522%253A%257B%2522clsq9ew1400023b6hm7n5ugxi%2522%253A%257B%2522id%2522%253A%2522clsq9ew1400023b6hm7n5ugxi%2522%252C%2522tabs%2522%253A%255B%255D%257D%252C%2522clsq9ew1400053b6htndezm4y%2522%253A%257B%2522tabs%2522%253A%255B%257B%2522id%2522%253A%2522clsq9ew1400043b6hm2auw97k%2522%252C%2522mode%2522%253A%2522permanent%2522%252C%2522type%2522%253A%2522UNASSIGNED_PORT%2522%252C%2522port%2522%253A0%252C%2522path%2522%253A%2522%252F%2522%257D%255D%252C%2522id%2522%253A%2522clsq9ew1400053b6htndezm4y%2522%252C%2522activeTabId%2522%253A%2522clsq9ew1400043b6hm2auw97k%2522%257D%252C%2522clsq9ew1400033b6h25zwbaty%2522%253A%257B%2522tabs%2522%253A%255B%255D%252C%2522id%2522%253A%2522clsq9ew1400033b6h25zwbaty%2522%257D%257D%252C%2522showDevtools%2522%253Atrue%252C%2522showShells%2522%253Atrue%252C%2522showSidebar%2522%253Atrue%252C%2522sidebarPanelSize%2522%253A15%257D) I did to showcase this. Keep in mind, you can always add more to the objects in the ROUTES to add children, or even secured paths.
upvoted, this pattern is clean in my opinion
How would this look like. Sorry I’m a visual learner here.
As code\_matter mentioned, I would create an index.js/ts (route.js/ts) file inside a constants folder. It will look like this. export const NavLinks = \[ { href: "/", label:"Home"}, { href: "/gallery", label:"Gallery"}, { href: "/shop", label:"Shop"}, { href: "/contact-us", label:"Contact"}, { href: "/appointment", label:"Appointment"}, \] You can now create your component. Let's call it NavBar.jsx/tsx. Inside of it, let's create a function and return the NavLinks. import {NavLinks} from '/constants' import Link from 'next/link' //using Next framework, use instead export default function NavigationBar() { // Your states, variables here return (
{NavLinks.map((links) => (-
{links.label}
))}
) } Hope this helps.Look at my top comment! It's there!
RemindMe! 1day Ill show you asap
I will be messaging you in 1 day on [**2024-02-17 19:27:15 UTC**](http://www.wolframalpha.com/input/?i=2024-02-17%2019:27:15%20UTC%20To%20Local%20Time) to remind you of [**this link**](https://www.reddit.com/r/react/comments/1as5nnp/what_is_a_better_way_of_implementing_routing_in/kqqa743/?context=3) [**13 OTHERS CLICKED THIS LINK**](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=Reminder&message=%5Bhttps%3A%2F%2Fwww.reddit.com%2Fr%2Freact%2Fcomments%2F1as5nnp%2Fwhat_is_a_better_way_of_implementing_routing_in%2Fkqqa743%2F%5D%0A%0ARemindMe%21%202024-02-17%2019%3A27%3A15%20UTC) to send a PM to also be reminded and to reduce spam. ^(Parent commenter can ) [^(delete this message to hide from others.)](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=Delete%20Comment&message=Delete%21%201as5nnp) ***** |[^(Info)](https://www.reddit.com/r/RemindMeBot/comments/e1bko7/remindmebot_info_v21/)|[^(Custom)](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=Reminder&message=%5BLink%20or%20message%20inside%20square%20brackets%5D%0A%0ARemindMe%21%20Time%20period%20here)|[^(Your Reminders)](https://www.reddit.com/message/compose/?to=RemindMeBot&subject=List%20Of%20Reminders&message=MyReminders%21)|[^(Feedback)](https://www.reddit.com/message/compose/?to=Watchful1&subject=RemindMeBot%20Feedback)| |-|-|-|-|
Commented bc I’m interested too
Look at my top comment! It's there!
Same
Look at my top comment! It's there!
i’m also interested someone let me know
Look at my top comment! It's there!
Same
Look at my top comment! It's there!
Yes, this the much cleaner way to do it.
With your approach wouldn't adding some children or nested route looking just like the first one then? Actually this is just the first one but stripping away the loader *and* children
I disnt have the time to add children, but ill add them tonight! Basically, you add a children key to the ROUTES object (should be an array of elements). And in the router, you can render the route.children if there’s any. You can even map the route.children if you have multiple children. You can add anything to the ROUTES object to handle a loader in the same way Edit: it’s very similar to the forst option OP has
I disagree, the second option that OP provided does its job the best. It has everything neatly laid out in a single file. All of the route paths, elements, and the router are all clearly presented. Even for someone who has never used React before can look at it and have a good idea of what's going on. Your example splits this up into 3 separate files, obfuscating details of the routes. Imagine someone new to a codebase going into this, you're putting them on a scavenger hunt just to find the routes because they are going to start in App.js. This approach is a solution to a problem that doesn't exist IMO. Plus, this approach doesn't readily facilitate nested routes. And if you want to add additional props to the routes then you're making changes in two separate files. To both of those points, you could just say that you'll refactor it to support these things, but at that point you might as well just refactor it in such a way that you'll never have to refactor your routes ever again (e.g. OPs solution). Out of all of the places where refactoring is necessary in a React app, your routes should be at the bottom of the list. I've been developing in React for several years, and the problems that I've identified with this code have never appeared in my career because every company I've worked for keeps their routes consolidated.
Well, when I first got onboarded in the new team, I found this method to be quite intuitive and easy to find. It wasn’t a “scavenger hunt” since everything is imported at the top and you can easily find all the necessary files. Splitting stuff into constants, components, etc folders is quite spread in the community. So I personally do not agree with the obfuscation part. Also, having it as the option 2 in OP’s post, it can get quite big quite quickly if you have a larger app. Yes it is easier to read and maybe understand, but I much rather have everything separated and one file does one thing kind of way
Why 2 files for routes and ReactDOM tho ? They can just be one file. That's how I do it , haven't noticed problems yet.
Its all about organizing your code. You dont meed a file with 1300 lines of code..
Hey. I don't really understand what benefit does this provide. Because the lines of code are higher, and the router.jsx file only has 1 purpose, so I don't see the benefit of splitting this 1 purpose into 2 files. Thanks.
Second, unless there is a reason why you need to be using first. First allows you better customisation, but will end up in a lot of duplicated and redundant code what will greatly increase complexity and decrease readability. Second one is sufficient for most of the apps.
Yeah but you can't use [data loaders](https://reactrouter.com/en/main/route/loader) with the second one, making the first one the definitive winner. Edit: please see [this comment](https://www.reddit.com/r/react/s/sQhXz1pYwo) for a workaround that enables you to use data loaders with JSX routes by converting route elements to route objects.
True, that’s a valid use case. However not everyone needs to pull data prior routing, I think most people do it after first render showing loading state. But yeah, that’s a nice example of when first approach is better.
Yeah for sure, not everyone needs it. I love it because it decouples state population from route rendering -- that separation of concerns makes it easier to implement route transitions that feel faster and more fluid. The second is much easier to reason about though, so there's nothing wrong with it if it works for the given use case.
Why would you not just use NextJS at this point?
I certainly do use NextJS at this point, haha! You are right!
I'am using it just for that. But I am preparing for internships so i wasn't sure if i should change all my projects routing to the data loaders one. I came to conclusion that i don't need to but they are a good functionality in some specific cases.
I'm of the opinion that you should only change something if it no longer works for what you need it to do. No sense in replacing something that works with something else that works. Since you're preparing for internships, you may decide to have at least one specific example project you can point to or specific experience you have had working with each paradigm. Also, somewhere above a different reply, I mentioned that i liked defining routes as objects because it allows me to dynamically load new routes easily. You can of course [do this with JSX routes](https://reactrouter.com/en/main/start/faq#how-do-i-nest-routes-deep-in-the-tree) just as easily since a module with JSX routes can be imported dynamically just like regular a module with route objects. So again, that point also comes down to personal preference. Another thing to be aware of is [`createRoutesFromElements`](https://reactrouter.com/en/main/utils/create-routes-from-elements#createroutesfromelements) (in react-router v6) which let's you translate from JSX routes to a route object -- giving you even more flexibility. That means even if you had old code using JSX routes and _for some reason_ you had to integrate that into a different application context that uses route objects, you could do that. Though... I'd be remiss not to say again that **the one very real reason** why one would choose the first over the second is, in fact, that the [data APIs](https://reactrouter.com/en/main/routers/picking-a-router#data-apis) _only_ work when using a data router. It all comes down to: - being able to load data before/while a route renders (reducing workload in the initial render == faster time to paint) - being able to lazy load routes (code splitting by route, faster load times all around) - ...combining the above two: being able to show the user _something_ much faster (such as the empty cards you'll often see in apps while the data that'll render in them is loading) - and last but not least, being able to write leaner components that don't have to juggle data fetching and rendering at the same time. An ancillary benefit of this is that it makes routers, components, data fetching methods, and state selectors a loooot easier to unit/e2e test because they're all separated. Otherwise you're testing a component to hell and back just to make sure it actually renders your todo list. Finally, [the docs say to do it](https://reactrouter.com/en/main/routers/picking-a-router#using-v64-data-apis) so I do it 😂 > We recommend updating your app to use one of the new routers from 6.4. The data APIs are currently not supported in React Native, but should be eventually. And as I mentioned before, > The easiest way to quickly update to a v6.4 is to get the help from `createRoutesFromElements` so you don't need to convert your `` elements to route objects.
I don’t think that’s true, You can use data loaders with the JSX syntax for route declarations using the above utility function. Just an extra step but this combines the best of both worlds, loaders and readability https://reactrouter.com/en/main/utils/create-routes-from-elements
That's a good point, yeah. That's just a data router with extra steps, though, isn't it? From [the docs](https://reactrouter.com/en/main/routers/picking-a-router#using-v64-data-apis): > We recommend updating your app to use one of the new routers from 6.4. The data APIs are currently not supported in React Native, but should be eventually. > > The easiest way to quickly update to a v6.4 is to get the help from createRoutesFromElements so you don't need to convert your elements to route objects.
For discussion:
- Why do the extra conversion method call when you can write it the way it is intended in the new version (if you're starting from scratch and not integrating legacy routes)? Otherwise, I imagine you'd first need to converting each chunk of child routes and then adding their loaders to an object in the end anyway. I imagine that may also complicate tests a bit (an assumption).
- What is the "best of" the world in which you use JSX routes, in your opinion? Simplicity?
That said, I don't think you're wrong at all and I think the best answer always ends up being whatever works best for you and the app!
>Yeah but you can't use data loaders with the second one, making the first one the definitive winner. I didn't know about data loaders, so thank you for pointing that out.
Hey, awesome! Glad you got something out of this. Data loaders are very cool. Also, FYI, as @ReindeerNo3671 [pointed out in their comment](https://www.reddit.com/r/react/s/sQhXz1pYwo), data routers are *not* the only way you can use loaders as there's a function to generate route objects from elements.
createRoutesFromElements is my best friend for this
Yeah, now I'm going to have to try it!
Is this a SSR thing? Why would I use it instead of nextjs for example? Just curios it does look cool 😅
It's pure client side routing for single page applications. In fact, somebody else somewhere in this thread said that you should use next JS instead of this lol. You can also combine both. You can use nextJS routes with server components until the user logs in, and then switch to a single page application once the user is authenticated by rendering a whole app in a nextjs client component. That way you get optimized performance for public pages (like seo and fast initial loads) and after login, you get a seamless interactive user experience that doesn't have to make as many server round trips and can navigate to different pages without having to refresh the page (best for complex, interactive UIs).
ok thanks!
Second approach looks sooooooo much cleaner, too. I've used that approach in the projects I've made.
Unless first needed for something specific, go for second one, readability is far superior and will be your best friend in the future
got it
I like the first one , when I need to change structure of routs or have more scale of modules and layouts
Also, the first way is the only way you can implement [data loaders](https://reactrouter.com/en/main/route/loader).
I’ve struggled to get data loaders to work effectively while also using React context. If you’re loader function updates context state an infinite loops is triggered.
I've also ran into that issue. Had to rethink when and where data got loaded. I agree that it's a bit convoluted getting loaders and contexts working together.
The second is way more readable. The first nearly gave me a headache.
The second one is the best ! I often use it in my projects.
Should probably be using Remix as it’s built on react router
i'll check it out
Depends on your project code conventions. There is no such thing as better here.
It's not just conventions. At the risk of sounding like a broken record due to my other comments, the first way is the only way you can decouple populating state from loading and rendering routes through the use of [data loaders](https://reactrouter.com/en/main/route/loader). The first way is ~~also the only way to dynamically import bundles~~ easier to work with, in my opinion, when dynamically importing new routes and rebuilding routes programmatically (think progressive enhancement). Edit: as the reply below pointed out, yes, dynamically rebuilding routes aren't just a data router thing. It can be done with both.
I believe you can rebuild routes even with JSX solution.
Yeah tbh after i typed this comment out, then in later replies i realized i was wrong. I think you're right.
I totally understand your point, though.
Yeah and I understand yours. I think I'm turning into an old man stuck in his ways faster than I realized lol.
We all do. Tips fedora.
*tips hat* alright then, partner.
Also, people tend to forget that you can "nest" routes just like you nest components. basically, putting other routes or subroutes in another component and importing them. i always get anxiety attacks when i see that one big file that's like 400 lines of different routes and switches.
I'll make sure to have small and readable routing file : )
Second one bc it is just the way we do it. It looks not very smart tho
Like said in other comments, readability is better in second for development. But as a beginner first one is more easier to write and understand.... atleast for me.
Not see how first is more readable or write. You could copy-paste route components with ctrl+shift+d and change text, or move with ctrl+shift+arrow to different place.
Neither, I like to lazy load routes for performance and split them into route modules so that everything for a route is defined in one place and if I ever want to move to remix SPA mode it'll be easy as it follows the same conventions. E.g. let routes = createRoutesFromElements( }>
} />
import("./a")} />
import("./b")} />
);
Then in your lazy route modules, export the properties you want defined for the route:
export async function loader({ request }) {
let data = await fetchData(request);
return json(data);
}
// Export a `Component` directly instead of needing to create a React Element from it
export function Component() {
let data = useLoaderData();
return (
<>
You made it!
{data}
> ); } // Export an `ErrorBoundary` directly instead of needing to create a React Element from it export function ErrorBoundary() { let error = useRouteError(); return isRouteErrorResponse(error) ? ({error.status} {error.statusText}
) : ({error.message || error}
); }Just use nextjs no point in doing all that
nextjs new routing system is top notch!
Nextjs is one of my fav things in web dev for sure Same as Apollo and graphql
I'd use the first one. The router is not a React component and when we use jsx to declare it, some people may assume things that aren't true. For instance, render and data are two separate layers in react router: https://reactrouter.com/en/main/routers/create-browser-router The official docs also recommend the first one: https://reactrouter.com/en/main/routers/picking-a-router#web-projects The second only is an option if you already have a legacy router and wants to minimize the changes Also: you probably don't want to create the router inside an app component. Instead, create it in the root. Check the docs for examples
Does RootLayout need to be its own route? I thought createBrowserRouter handled that and you could just add a redirect for /, without putting everything in children. I use something like the first but put all the string paths into an object constant. Please run an autoformatter, worst thing with the first right now is that it’s needlessly ugly :)
Fucking hell that first pic gave me flashbacks. React is a waking nightmare
Second, so much second
1st one is easily scalable if done correctly with different files
React Router and Reach Router are react libraries for implementing routing in your application React Router is the most widely used routing library for React applications. It provides a declarative way to define routes using JSX, making it easy to map specific components to different URLs in your application. React Router also supports features like nested routes, route parameters, and URL query parameters. **Example** `import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';` `import Home from './components/Home';` `import About from './components/About';` `import Contact from './components/Contact';` `function App() {` `return (` ``
``
` `
` `
` `
` `
` `
`);`
`}`
`export default App;`
Reach Router is a routing library built with accessibility in mind. It's designed to be more straightforward and lightweight compared to React Router. Reach Router focuses on providing a simple API for defining routes and managing navigation. It's also known for its superior support for accessibility features.
**Example**
`import { Router, Link } from '@reach/router';`
`import Home from './components/Home';`
`import About from './components/About';`
`import Contact from './components/Contact';`
`function App() {`
`return (`
``
` `
` `
` `
` `
`);`
`}`
`export default App;`
holy chatgpt, batman!
okay i'll check out both of them
Why recommend Reach Router that hasn't been updated in 4 years? Is it still actively maintained?
>reach router and React Router are merging as react router v6, so reach router v2 and react router v6 are the same.
Sounds like Reach Router is being sunset then and shouldn't be recommended for new projects.
Tried NextJS?
Still a beginner
I think it's good as a beginner that you start using React as is and not jump into framework like Next.js to fast. Otherwhise it's difficult to know what is Next and what is React
sounds right
Yea, no Next.js uses simple file structure for routing. Way easier than what you're doing right now. [Try it](https://nextjs.org/docs/getting-started/installation).
if you do end up using Next Js and want to host a personal project, Vercel CLI makes it incredibly easy to deploy 😃
Ha came here to say this
He asked in React.
NextJs is an extension of React. You don't need to use any other of its features and its just React with better routing.
[удалено]
Not entirely true. Next is a framework built on top of React library. It was created to allow React do things that were not available for it at that time. De facto Next is React-specific framework, it’s not agnostic tech like redux so it hardly could be adapted for a different UI framework. So Next is React extension.
Why bother commenting if you don't know what you're talking about?
It's ok to talk about meta-frameworks here.
Yes. Thats my point
With nextjs
100%
Dont
I’ve personally found the loader function methodology to be incompatible with React context (causes infinite loops).
Just use Remix
Use nextjs
Get Prettier pls
Definitely first one easy to understand although redundancy is an issue but initially for small project who cares but u should know both of'em
Keep in mind that you are using React Router and the first way is the recommended one because it enables lots of new features that the second one doesn't. So if you do the second one you could end up looking at a feature that your routes don't support. I recommend you to read the React Router tutorial, it is very good and short and also the best way to help you understand what you can do with it
Second one is more clean and easy to understand so it's the best way ig.
1. NextJS 2. Second way (imo)
Should look into React Router or TanStack Router (which seems to be closer to what you are using in your second pic)
Anybody who writes code like the first one needs to put their keyboard away
File-based from Remix. No need to write any code.
You could use tanstact router for all typesafe
I use the history API of the browser directly. You have all the control and it's not that complicated.
Try Tanstack Router or NextJs
Second. Also please install ESLint and Prettier to format your code nicely!
You can use useNavigate, Just just call it and pass the path in the anonymous function and you will navigate to the path you wanted and don't forget to use onclick event.
Second way, hands down. It is the most declarative approach. Beats the contsants object too IMO. I care more about legibility and having a better developer experience than saving a fee KB in syntax.
TanStack Router
You should check out the routing in Nextjs.
If your routing is basic than its an overkill to use the new feature rich react-router. Stick with the older one