React-Router out of sync with window.location? - react-router

I'm having trouble getting client-side routing to work properly (with react-router-dom#5.2.0)
I have an <Application> component which returns:
<BrowserRouter>
<Switch>
<Route path="/:filter/:id">
<Something...>
</Route>
<Route path="/">
<SomethingElse...>
</Route>
</Switch>
</BrowserRouter>
Whenever I navigate to [localhost]/rating/good, things work as expected: the proper route is matched (ie. "/:filter/:id") and the <Something> component is rendered.
I have a button which clears what I call filters; whenever I click on it:
I update the URL with useHistory().push('/')
The change is immediately observed
I update of my AppState, which triggers an update of my <Application> component, which in turn means <BrowserRouter> and <Route> are updated.
And that's when I observe something I didn't expect:
The same route as before (ie. path="/:filter/:id") is matched and the <Something> component is rendered -- despite the current URL pathname being "/".
Is this the expected behavior?
If yes, what is react-router using to match routes if not the current window.location?
Now I've got it to work (I think) by updating <Application> with:
const location = { ...useLocation(), pathname: window.location.pathname }
And passing that location object as such:
<Switch location={location}>
But it feels like I'm doing something wrong and that it should have worked without me fiddling with the location object.
Thanks for any hints!

Related

Property 'component' does not exist on type

Why do I get this error when I declare a "component" property in "Route";
Property 'component' does not exist on type 'IntrinsicAttributes & (PathRouteProps | LayoutRouteProps | IndexRouteProps)'.
import { Routes, Route } from 'react-router-dom'
import './App.css'
import HomePage from './pages/HomePage'
function App() {
return(
<div>
<Routes>
<Route path="/" component={HomePage}/>
</Routes>
</div>
)
} ``` The problem might be; because I dont use 'exact path="/"' that might also give an error
With the upgrade of react-router-dom to version 6.0, certain properties have changed. The syntax you are using will work fine for version 5.0. To update to v6, make this change to your code:
<Route path="/" element={<HomePage />} />
I solved it by simply typing this instead;
<Route path="/">{HomePage}</Route>
And it worked
Version 6 of the router changed the way to create these kinds of routes - https://reactrouterdotcom.fly.dev/docs/en/v6/getting-started/overview
nanoTitan got the right answer with:
<Route path="/" element={<HomePage />} />
Regarding exact - I do not think you need to worry about this any more. If you have a route like / and another route like /about version 6 is smart enough to route to about. Apparently, even if you have routes like /user/:uuid and /user/new - navigating to /user/new will be understood as the new page.
I also found that tutorials and the like are all about version 5, it is a confusing environment to learn in.
Just switch version of react-router-dom to "^5.1.2", and #types/react-router-dom: to "^5.1.3"

React Router with mix of Fixed Routers and Dynamic Route

I am having routes like
/: Login
/A: A Component
/:[dynamic] : B Component
Now I am using code Like below, but now every time Component B is loading, even if i pass "Exact" keyword too.
<Route exact path="/">
<LoginComponent />
</Route>
<Route exact path="/:dynamic" component="Dynamic' />
<Route exact path="/A" component="A" />
this happens because the router can not distinguish between the dynamic value or "A" or "".
as I know you can't solve it without make another route for B component, like "/basicPath/:dynamic"

How to set an optional parameter on root route in react-router v4?

Let's say I have the following 2 routes:
...
<Route exact path="/:param1?/" component={Home}/>
<Route path="/news" component={News}/>
...
now when I try to hit route /news the root route for Home with the parameter param1 is triggered...
I assume the solution would be to set a questionmark before the param1 like this /?param1 so it can be held appart from the routes, but I can not figure out how to do this in react-router v4
There's an example of how to do this in the official docs. You can find that here.
You'll need to use the Switch component with your /news Route being first.
<Switch>
<Route path="/news" component={News}/>
<Route exact path="/:param1?/" component={Home}/>
</Switch>
Switch will always only render one Route. So in the case above, if /news doesn't become active, then /:param1 will be.

Cannot GET /profile in React Routing

Im fiddling with React routing and I have just two different components. When I try to render my second component I get Cannot GET /profile
My routing looks like this
render((
<Router history={browserHistory}>
<Route path="/" component={Main}>
<Route path="/profile" component={Profile}/>
</Route>
</Router>
), document.getElementById('app'))
but my /profile component returns the error message when I visit localhost:3000/profile
Do I need to put render them from another component, or what seems to be the issue?
Remove the / from /profile, it should work. You don't have to explicitly prepend / if it is already in the parent route.

Accessing URL params in parent components

I've got an interesting conundrum that I'd like some insight on. I've got a routing setup like follows:
<Router history={hashHistory}>
<Route path='/' component={Main}>
<IndexRoute component={Home} />
<Route path='foo' component={FooContainer}>
<Route path='bars/:barId' component={BarDetailsContainer} />
<Route path='baz/:bazId' component={BazDetailsContainer} />
</Route>
<Route path='things' component={ThingListContainer}>
<Route path='thing/:thingId' component={ThingDetailsContainer} />
</Route>
</Route>
</Router>
And it works by and large. FooContainer has a child of its own (not via this.props.children), which wants to know what :barId is (and :bazId) when those components are loaded via their respective routes. Is there a way to access all of the current params -- including the URL params for its child routes -- from the "parent" component, FooContainer?
Note: it is also possible that I am doing this entirely wrong, in which case, I would love some advice on a better way to accomplish my goal here.
An answer, for those concerned:
Turns out I was looking for this.props.params in a child of Main that is not managed by any Route, and as such, I'd need to explicitly pass the params prop (or whichever params are important) down to it from Main.
My Main's implementation, as a rough JSX sketch, looks like:
<div>
<SomeOtherComponentThatWantsParams />
{this.props.children}
</div>