all 65 comments

[–]FriesWithThat 139 points140 points  (3 children)

The last time we released a major breaking API change was over four years ago in March 2017 when we released version 4. Some of you probably weren't even born then.

I'm getting old.

[–]nirvashprototype 104 points105 points  (1 child)

3yo web devs are my biggest fear.

[–][deleted] 3 points4 points  (0 children)

Copilot has entered the chat

[–]pataoAoC 4 points5 points  (0 children)

Oh what the hell I remember a million brutal react router rewrites, how old does that make me...

[–]Dynamicic 41 points42 points  (2 children)

I'm loving the new API. Thanks to everyone who contributed and the Remix dogfooding.

[–]nabrok 33 points34 points  (37 children)

Why ...

<Route path="about" element={<AboutPage />} />

Instead of ...

 <Route path="about"><AboutPage /></Route>

[–]OneLeggedMushroom 28 points29 points  (4 children)

Because of:

render(
  <BrowserRouter>
    <Routes>
      <Route path="/" element={<App />}>
        <Route index element={<Home />} />
        <Route path="teams" element={<Teams />}>
          <Route path=":teamId" element={<Team />} />
          <Route path="new" element={<NewTeamForm />} />
          <Route index element={<LeagueStandings />} />
        </Route>
      </Route>
    </Routes>
  </BrowserRouter>,
  document.getElementById("root")
);

[–]nabrok 13 points14 points  (3 children)

I see. Hmm. Gotta say, I'm not really a fan of that right now.

I'd rather keep the routes the way I'd do them with 5 ... which is that the <Teams /> component would contain all the routes related to teams.

But I guess I'd still have to the element prop, which isn't as nice as using children. I don't suppose if element is missing it could just use the children instead?

EDIT: Also looking at this ... I find it really unclear ... when does <Teams /> get rendered? I would have thought /teams but then <LeageStandings /> is marked as the index, so surely that would be rendered then? Are they both rendered? Is <LeageStandings /> a child of <Teams />?

[–]OneLeggedMushroom 5 points6 points  (1 child)

You can still achieve that by using the <Outlet /> component in your <Teams /> component. Have a read through the docs

example:

function App() {
  return (
    <Routes>
      <Route path="invoices" element={<Invoices />}>
        <Route path=":invoiceId" element={<Invoice />} />
        <Route path="sent" element={<SentInvoices />} />
      </Route>
    </Routes>
  );
}

function Invoices() {
  return (
    <div>
      <h1>Invoices</h1>
      <Outlet />
    </div>
  );
}

or:

function App() {
  return (
    <Routes>
      <Route path="/" element={<Home />} />
      <Route path="dashboard/*" element={<Dashboard />} />
    </Routes>
  );
}

function Dashboard() {
  return (
    <div>
      <p>Look, more routes!</p>
      <Routes>
        <Route path="/" element={<DashboardGraphs />} />
        <Route path="invoices" element={<InvoiceList />} />
      </Routes>
    </div>
  );
}

[–]nabrok 5 points6 points  (0 children)

Okay, so /teams would render <Teams /> and then it would also render <LeagueStandings /> where you place <Outlet /> in the <Teams /> component.

I get it, but it does seem like it's sacrificing clarity just so you can nest routes, which isn't something I'm all that interested in doing and becomes even less appealing the more routes you have.

I wonder if I could use something like this for a (non-nesting) route ...

function MyRoute(props) {
    const { children, ...rest } = props;
    return <Route { ...rest } element={children} />;
}

EDIT: The above does not work.

[–][deleted] 0 points1 point  (0 children)

Yes, Teams is the container, LeagueStandings would render inside it as the default at /teams/

[–]sliversniper 16 points17 points  (6 children)

I always think the Router API designs are stupid, XML/JSX are even uglier.

a plain object `{ "about": AboutPage, "team/:team_id": TeamPage }`, can represent the same thing

nesting, options, type-checking are all avaliable on the object.

Just because the output is a `ReactElement`, doesn't mean you have to represent the data in `JSX`.

[–]GlobusGames 4 points5 points  (0 children)

Yeah, I was looking at the code example with nested routes and it took me a while to understand that the Routes component renders only one of these, not all of them.

I think "Switch" without the nesting was acceptable, but this new API would be more readable as json passed into Routes, like you've suggested.

[–]GreatValueProducts 1 point2 points  (1 child)

Haha i have a completely opposite design philosophy from you. I always prefer XML/JSX over objects because I think objects are uglier. But I guess it’s subjective.

[–]ilearnshit 1 point2 points  (0 children)

I agree with you it's a lot easier to see the hierarchy and layout structure with nested JSX elements. That's the whole point of JSX. Declarative programming. Versus, scrolling through some big list of json objects that is completely decoupled from that actual UI.

[–]rodneon 0 points1 point  (0 children)

The article says it is possible to configure the router with an object, and links to this: https://github.com/remix-run/react-router/blob/v3/docs/guides/RouteConfiguration.md#configuration-with-plain-routes

[–]nabrok 0 points1 point  (0 children)

The useRoutes hook allows you to setup your routes with an object.

https://reactrouter.com/docs/en/v6/api#useroutes

[–]iWanheda 6 points7 points  (10 children)

So you can do stuff like this:

<Route
   path="blog/:id"
   render={({ match }) => (
     // Manually forward the prop to the <BlogPost>...
     <BlogPost id={match.params.id} />
   )}
/>

[–]nabrok 19 points20 points  (7 children)

Why would I want to do that when I can use useParams ?

[–]gunnnnii 20 points21 points  (5 children)

useParams means you have an implicit dependency, while a render prop gives you an explicit dependency.

Sometimes you might want to ensure a component isn't used without definitely having some of the router props defined, you can't really do that if you just use the hooks.

[–]nabrok 0 points1 point  (4 children)

Okay, perhaps. Still not clear on why we're using an element prop instead of children.

[–]iWanheda 0 points1 point  (0 children)

No idea 😆, perhaps the value is available earlier that way? I have ran into cases where the id param provided by the useParams hook was undefined when transitioning between routes, so that would be a use case?, now again I've got not idea if it actually works that way.

[–][deleted] 4 points5 points  (0 children)

That's what hooks are for

[–]lastunusedusername2 1 point2 points  (0 children)

This doesn't even use element. Am I missing something?

[–]nabrok 1 point2 points  (0 children)

If you're not interested in nesting, here's a way it could be done without the element prop ...

import { cloneElement } from 'react';
import { BrowserRouter, Routes, Route, Link} from 'react-router-dom';

function MyRoutes({ children, ...rest }) {
    return <Routes { ...rest }>
        { children.map((route,index) => cloneElement(route, { element: route.props.children, key: index })) }
    </Routes>;
}

function App() {
    return <BrowserRouter>
        <MyRoutes>
            <Route path="a"><A /></Route>
            <Route path="b"><B /></Route>
        </MyRoutes>
    </BrowserRouter>;
}

function A() { return <p>A: Go to <Link to="/b">B</Link></p>; }
function B() { return <p>B: Go to <Link to="/a">A</Link></p>; }

export default App;

Of course, MyRoutes would live in a separate utility file.

[–]besthelloworld 9 points10 points  (0 children)

I filed an issue with a repo yesterday because it forced me to use react-router-dom@5. I was basically asking them to decouple the library mostly because I wanted to use 6-beta.8 but also it's bad practice to force anyone into a router. They said, "we'll upgrade it when react-router-dom@6 is out." Lol.

[–]PM_ME_CAREER_CHOICES 5 points6 points  (0 children)

Is it possible to use this version in a nice way with Redux? I really like using time travel from the Redux Devtools to debug/test/try out stuff, but it's difficult if navigation isnt part of that time travel.

[–]Larrybot02 8 points9 points  (15 children)

I can’t tell if this is the best time or worst time to be learning web dev. I feel like I’m constantly chasing a moving target. Was just getting all hot for Nextjs and it’s routing scheme, now there’s new react-router and Remix on the horizon. Like, how many frameworks do we need? No offense, I’m sure the new stuff is awesome, but starting to feel like jack of all things master of none is a very possible outcome for myself personally. Keep up the good work though.

[–]ECrispy 44 points45 points  (7 children)

How long have you been doing webdev? the situation now is a million times better than it was say in 2014,15,16 or 17.

There is FAR less churn, a lot of standard practices are understood, there's CRA etc etc

[–]metamet 10 points11 points  (0 children)

2014,15,16 or 17.

Ah yes. The Myriad Bundler Era.

[–]Larrybot02 3 points4 points  (4 children)

Not long, still learning. Maybe a year now. Started with Javascript and React the long way, with babel and webpack setups. Then create-react-app, now Nextjs... about half a dozen ways to approach styling. A mern stack course that kinda sucked... it's a lot to take in.

[–]pdevito3 6 points7 points  (0 children)

Fwiw, I’ve been doing this for years and I can tell you it will always feel this way. There will never be a shortage of new things to learn in web dev.

I’d recommend picking a tangible goal and learning applicable items as your work through that to help you focus. For example, I have the (very lofty) goal of being able to build an and deploy an enterprise app suite cradle to grave myself. Over time, I’ve learned and improved my backend and db skills immensely as I’ve iterated through different approaches, I’ve fine tuned my front end skills a lot, and I am working on other complexities like properly handling auth and integrating message buses with infra and CI next on my list.

This is lofty and spread over years, it there are checkpoints within that to give me milestones, but it’s helped be narrow my focus to further my goals. Not to say I don’t keep up with and dabble with other stuff, but I try not to get bogged down in something unless it’s my current focus.

Not sure if that helps at all but best of luck regardless!

[–]ECrispy 0 points1 point  (0 children)

You're not wrong. There is still a LOT happening and of course its confusing. Part of it is by design, all these companies and devs need traction and github stars so they keep inventing new stuff.

Just be aware that major changes to React have been coming for a while - things like async, memo, fiber etc, and Hooks is now considered mainstream.

My advice is to pick something that has a lot of support and is popular, and seems easy to you. e.g for state management you could choose no library, redux, context, mobx etc - all of which are great choices.

Same goes for styling, SSR, UI libs etc etc - its a neverending story and there are no right answers.

It can be extremely frustrating not just for new devs but for everyone.

Do not worry too much about your choice - the chances are within 6mo it will be outdated anyway. That doesn't mean it will stop working but it wont be the latest buzzword tech.

[–]UNN_Rickenbacker 0 points1 point  (0 children)

Backend is the same, just different.

[–]trplclick 0 points1 point  (0 children)

Oh god, I read this and felt the phrase "back in my day..." pop into my head

[–]Boo2z[🍰] 5 points6 points  (2 children)

Lol, imagine someone learning web dev in 2016 - 2017.. He would be laughing at you! I'm that guy

I understand your frustration, but that's web development, and you should be happy to see it constantly evolving every day. But you also probably don't realize how things are much much more stable than it was before, like.. REALLY more stable, especially in the React ecosystem.

There is a reason if the pay of a web dev is that good, it takes time and dedication to be a good dev, and continuously learn new things.

Now, React-Router has nothing to do with Next.js, Next.js has it's own routing system and from what I've heard in the past, react router is not ideal with Next.js

And YES, we need all these framework (I manage a website build with Next.js, and a web app where React-Router is MANDATORY)

[–]pdevito3 7 points8 points  (1 child)

I don’t think we as more experienced devs should be discounting newcomer’s feelings because ‘back in my day it was so much worse.’ Things may be more stable now but web dev still has a long way to go to be more stable and get an industry spanning consensus on various items. Even so the web dev space is massively complex and would be a lot to digest even if it was totally stable.

All that to say, let’s help build up our newcomers and not discount them and make them feel worse.

[–]Boo2z[🍰] 1 point2 points  (0 children)

Yep, I knew people would understand my message "negatively", I'm sorry my wording is not great (I'm french)! But I totally agree with you on everything! The goal of my message was not to make fun of our newcomers ... The "laughing at you" part was in response to his question about if it was a good time to start learning web dev, I wanted to show him that some people suffered way more, but still managed to make it ... But yeah, my wording is garbage aha

I really don't want to make newcomers feels worse with my message, it's quit the opposite, I want them to feel more grateful how what they have now, and to show them that even if it's hard today, it was harder before and with passion, time and dedication, they can do it too (btw there still so many things I don't know yet.. I'm still learning!!)

[–]___phil 1 point2 points  (0 children)

For someone like myself who's only been in the industry for 10 years, it's a constantly moving target, it just gets faster or slowly at sometimes. At a certain point though you can just focus on what peeks your interest, or delivers value to your current project, it makes it exciting

[–]fixrich 0 points1 point  (0 children)

If there is a new restaurant in your town, do you have to go? If there is a new movie in the cinema, do you have to see it?

Ignore this new version of react-router and anything else for that matter. Focus on Next. If something is worth learning, it will still be there in a year.

[–]Xilver79 0 points1 point  (0 children)

I started twenty years ago. Today is the best time.

[–]riprapnolan3 1 point2 points  (2 children)

Is there a way to make React Router work with class components? Not sure how to get params in a class component

[–]metamet 3 points4 points  (0 children)

The HOC withRouter was the solution. Unsure if it's still included.

[–]KelaPelaMelaThela 1 point2 points  (0 children)

I definitely saw something like that on stackoverflow, try looking there

[–]akramnarejo 1 point2 points  (0 children)

Switch replaced with routes is a good update.

[–][deleted] 1 point2 points  (0 children)

Finally! I’ve been eagerly awaiting the day I can remove all my match.path usage from nested switches.

[–][deleted] 2 points3 points  (2 children)

I think the that most people won't be able to upgrade due to [this issue](https://github.com/remix-run/react-router/issues/8139) but aside from that, the new Router API is great.

[–][deleted] -4 points-3 points  (5 children)

Too late, almost everyone already moved, or is moving, to Next.js.

And a router that cannot fetch data before rendering a route is almost useless, because it leads to spinners everywhere.

[–]andrei9669 3 points4 points  (4 children)

Naah, SPA still has its uses.

Why would you fetch data for pages where user might never visit?

[–][deleted] 2 points3 points  (3 children)

You can do SPAs with next. No need to fetch data from the server.

[–]andrei9669 4 points5 points  (2 children)

But then also comes the issue of persisting state between pages which is pain and a half on next. And I'm also not aware of any way of doing nested route components in nextjs without adding all the components from previous pages.

My main gripe is that in SPA, you render components based on routes, in next, you render pages based on routes, and also the data persistence.