React-router not matching query string - reactjs

My routes are defined as follows:
<Router history={browserHistory}>
<Route path="/" component={App}>
<Route path="experiments">
<IndexRoute component={Experiments} />
</Route>
<Route path="*" component={NoMatch}/>
</Route>
</Router>
When I visit /experiments, things work as expected and the Experiments component is rendered. However, when I manually enter a URL with query parameters, example: /experiments?offset=50, the route doesn't match!
But when I navigate using <Link to={{ pathname='/experiments', query={offset:50} }} />, things work as expected. The Experiments component is rendered and this.props.location.query.offset is set to 50.
How do I get the Route to match when a URL with query string is entered manually (or copy-pasted)?
It seems route should match automatically url-with-query-‌​string-not-matching-‌​react-router-route, but it doesn't seem to be working for me.
Edit:
I narrowed down the problem to the catch-all route path="*". When I remove this route, everything works (e.g. when I visit /experiments?offset=50). But no routes are matched when the catch-all Route is present, even though it is at the bottom of the precedence list.

You need to make use of historyApiFallback with history={browserHistory} to load your route when you manually enter it.
what historyApiFallback does, is make it so your server returns index.html for whatever URL you try to access and since your routes are then configured with respect to index.html so you can access any of the route url directly
In you webpack add
devServer: {
historyApiFallback: true;
}

Ok, turns out this was an entirely unrelated issue. I was using redux-auth which was causing a redirect to the wrong URL pathname. This was happening after the react-router did its parsing and route matching. Once I fixed that, route matching worked perfectly. I was able to parse the query string from a URL like /experiments?offset=50 using the Route config in my question above.

Related

React react-router-dom question how to have "/" treated as a string in the url route

I am trying to have URLs be unique identifiers in my route. This requires "/" be treated as strings somehow. I was wondering if someone knew how this could be done?
Here is an example of the code.
<Routes>
<Route path=":url" element={<UrlPage />}} />
</Routes>
So lets say we go to www.website.com/https://stackoverflow.com/questions/ask
I would want "https://stackoverflow.com/questions/ask" to be the URL. How do I get the entire "https://stackoverflow.com/questions/ask" to be treated as string by react router.
Update:
The following will treat everything a string but if a URL has a ? everything to the right will be ignored.
<Routes>
<Route path="*" element={<UrlPage />}} />
</Routes>
This isn't a good idea in general - not only will you have to set this up serverside to deploy this somewhere, but URLs containing / shouldn't be used as subdirectories.
If you really need to, I would URL-encode the address first like this:
www.website.com/https%3A%2F%2Fstackoverflow.com%2Fquestions%2Fask

How do I avoid rendering a component when another component in a similar path has already rendered when using URL params in React Router v4?

I'm trying to create RESTful routes for my application, but I'm having problems when it comes to routes with URL params.
Here are the routes that I want to have:
/accounts
/accounts/new
/accounts/edit
/accounts/:id
These is what my router looks like:
<Router>
<Route exact path="/accounts" component={AccountsList} />
<Route exact path="/accounts/new" component={AccountCreate} />
<Route exact path="/accounts/edit" component={AccountUpdate} />
<Route exact path="/accounts/:id" component={AccountDetail} />
</Router>
/accounts works fine, but when I go to /accounts/new or /accounts/edit, it also renders AccountDetail which is supposed to be located at /accounts/:id.
For the record, that I get that this is the correct behavior since /accounts/:id technically matches /accounts/new and /accounts/edit.
My question is if there's a way to make :id match with a specific pattern only (numbers only).
Try the < Switch> component of reactRouter.
Renders the first child < Route> or < Redirect> that matches the
location.
I think it's exactly what you are looking for.

ReactJS Values In The URL Always Visible

I have a filter system for my products in ReactJS which basically has the following:
http://localhost:3000/category/women/subcategory/tops/sorting/null/price/null/size/null/color/null/brands/null/merchants/null
The Route is as follows:
<Router>
<Route path="/category/:cat/subcategory/:subCat/sorting/:sorting/price/:price/size/:size/color/:color/brands/:brands/merchants/:merchants" component={Products} />
</Router>
The Problem is that I want to show filters in the URL in when they have a value other than null. Current my component works but I have to display every single filter in the URL with a null value by default, this is causing my URL to be extremely long. The only way I thought possible was to do a permutation combination of all the possible URLs in the filter and direct them all to { Products } which is extremely silly. There must be something in the Router component that I'm missing?
You need to use optional params in this case.
As and example if you want to accept both sorting/ascending/price and sorting/price you can write your path as follows assuming you use react router v4.
<Router>
<Route path="sorting/:sort?/price" component={Products} />
</Router>
You can read more about this here: React Router with optional path parameter

how to add slash in react router path

I have developed a page with react whose route is
http://example.come/page1
When the url is loaded I need to append a slash at the end of the url like this
http://example.come/page1/
My Routes are like this
Router history={browserHistory}>
<Route path='/' component={Home} />
<Route path='/page1' component={Page1} />
</Router>
I tried to change the path directly to "/page1/" instead of "/page1" but this will not load http://example.com/page1 , It will open only http://example.com/page1/
I want both the path to load the Page1 component
According to this reply, https://github.com/ReactTraining/react-router/issues/820#issuecomment-256814655
Using hooks (onEnter and onChange) with react-router v2 or above may achieve what you need.
Above answer will work fine and you will achieve what you need. But there is a catch. Open developers tool and click on network tab then refresh your page....you will see status 302 page redirect from WITHOUT trailing slash path to WITH trailing slash path.
And this is not very good. Atleast set status to 301.
How to set status ? https://github.com/ReactTraining/react-router/issues/458
Better resolve the problem from web server, like Nginx, which rewrites the url to add the trailing slash at the end of url.

Unit testing route matching with React Router 2

I’m trying to add unit tests for a React application and would like to test the routes provided by React Router (2.0.1). I’d like to test whether specific paths that I supply will match a route. I am writing my tests using Mocha and expect.
I’ve looked through the documentation on the React Router repository, but the only testing guide I could see was explaining how to test a <Link /> and how it’s rendered.
Say I have the following code:
// import statements omitted for brevity
export const routes = (
<Route path="/" component={App}>
<IndexRoute component={Index} />
<Route path="/foo">
<IndexRoute component={FooIndex} />
<Route path="add" component={FooAdd} />
<Route path=":fooId" component={FooDetails} />
</Route>
</Route>
)
ReactDOM.render(
<Router history={browserHistory}>{routes}</Router>,
document.getElementById('app')
)
How can I test that the routes created in the routes variable would match the following:
/
/foo
/foo/add
/foo/25
But not routes like:
/foo/bar/12
/bar
Essentially I want to check that every expected URL format has a route that will match it and that unexpected URLs don't match any routes.
I’m not interested in the elements that are rendered by the routes, so don't want to base my tests on checking whether a specific thing is rendered, only that a matching route was found and preferably some way of checking that it was in fact the expected route (I'd guess checking what the name of the component is or something?)
Any help is gratefully appreciated.
Thanks
We test exactly this in our test for matchRoutes: https://github.com/ReactTraining/react-router/blob/v3/modules/__tests__/matchRoutes-test.js
You can follow this pattern. If you can't identify your routes by reference, you can indeed assert on the components that were rendered as well.
As matchRoutes isn't exported, you'll want to use the match helper (otherwise used for for server-side rendering) instead, and check renderProps.routes or renderProps.components.

Resources