react-router-dom with multiple query strings does not work - reactjs

I am new to react router. I use react-router-dom 4.2.2
in my router set up I have:
<Route path={"/confirmuser/:confirmation_code/:username"} component={ConfirmUser} />
and here is a sample url I am trying to achieve:
localhost:3003/confirmuser?confirmation_code=986797&username=5f1
As you see I am trying to send multiple query strings.
in the confirmUser I read the query strings as follow:
console.log(this.props.match.params.confirmation_code);
console.log(this.props.match.params.username);
However I do not even get directed to this component and it seems react is not able to route to that page properly.
Any idea?

React-router v4 doesn't parse query strings anymore, so you either have to do the parsing yourself (not recommended), or use a package like query-string. An easy way to access the values is with a wrapper component, like this:
import * as queryString from 'query-string';
..
const WrappedConfirmUser = () => {
const {confirmation_code, username} = queryString.parse(location.search);
return <ConfirmUser confirmation_code={confirmation_code} username={username}/>;
}

You are trying to map search-params to path segments?
The Route you defined will try to match the path, not the search params.
Try:
http://localhost:3003/confirmuser/986797/5f1
and the values will be in this.props.match.params like this:
{
confirmation_code: '986797',
username: '5f1',
}
if you still want to read the search params, you can access them from this.props.location.search, but react-router will not match them to a route for you.

Your path doesn't match your url.
It matches localhost:3003/confirmuser/986797/5f1
Then you can access params using extra prop match:
{props.match.params.confirmation_code}
{props.match.params.username}

Related

React Router: How to properly append to route/url without replacing anything?

How do I append to the route with react router?
Let's say the current route is /page1/page2 and I want to route to /page1/page2/next-page
first I get the router
const router = useHistory();
When I use push like this
router.push("next-page");
It routes to /page1/next-page.
When I use add a / like this
router.push("/next-page");
It routes to /next-page
I also tried something like this
router.push(`${router.location.pathname}/next-page`)
But the problem this way is, when I'm currently at /page1/page2/, I end up at /page1/page2//next-page with two //.
Is there a good way to solve this without having to write the complete route like router.push("/page1/page2/next-page")?
What I ended up doing is defining a function that removes an / form the url if there
export const removeSlashSuffix = (input) => {
if (input.charAt(input.length - 1) === "/") {
return input.substr(0, input.length - 1)
} else {
return input;
}
}
and then route like this
router.push(`${removeSlashSuffix(router.location.pathname)}/nest-page`)
This way I get no issues with routes that resolve in url with // in it.
This is somewhat of a hacky solution and I wish react-router-dom would support this out of the box but it doesn't seem like it does
If you do router.push("/page1/page2/next-page"), it should work. I think you need to specify the full path, I don't see anything wrong in doing so
if you want to append something to an existing path, you should be able to do something like
const location = useLocation()
const currentPath = location.pathname // to get current route
router.push(`${currentPath}/next-page`)
THis is a sudo-code, so you may need to tweak it a bit for proper syntax

XML sitemap for react app

I have a react app for which I want to add a sitemap.xml. I have added this route to link to the file (XML is my my sitemap.xml):
import XML from './sitemap.xml';
<Route component={XML} path={'/sitemap.xml'} />
I keep getting this error, which I understand it means that I need to add an xml loader to my webpack:
You may need an appropriate loader to handle this file type.
Not sure how to pick an xml loader as I could mostly find parsers (xml to json) and I am not sure if it's ok to have the sitemap in json. Also, is there any other native way of displaying the xml file without adding any loader?
If you are using create-react-app, just put your XML file in public folder (a folder beside node_modules and src folders), then access it through {base_url}/{XML_file_name.xml} (e.g. localhost:3000/sitemap.xml)
In , keyword component should be a React Component.
Check the documentation:Route - React Router
If you want to pass XML as a variable, you should change XML format to string and with another prop but component={}.To transform XML to String, ry escape(XML) before passing to Route! Check escape(str)
with import keyword, youcan try like this:
// file: get-xml.js
let transformXMLToString = () => {
// read the target XML fiel and transform it to String
// return the string
return XMLasString;
};
export transformXMLToString;
// then you could import the XML like this in another file:
import transformXMLToString from 'get-xml.js';
// then pass it to <Route> like:
<Route component={transformXMLToString()}/>
A simple solution would be to add
<a href="XML_PATH" style={{display:"none"}}>xml</a>
Then check your google chrome development console, search for the anchor(a) tag.
And follow the path

Backbone.js routing with url as query string

I have Backbone js application and i have setup the router and now i try to pass url parameter as query string.
routes: {
'login?r=:query': 'doSomthing'
}
Can someone help me to pass url(http://someurl.org/dsfgsdjfsdgf) us query parameter.
For this question i found the right answer
router: {
'login?r:*query': 'dosomthing'
}

Routing in NancyFX

A sample route in Nancy can be like:
Get["/method/key1={value1}/key2={value2}"]
which can be reached by calling it as:
/method/key1=foo/key2=bar
I want to write the querystring in below manner:
method?key1=value1&key2=value2
What would be the route for this?
It will be the following route:
GET["/method"] => x
{
var key1 = Request.Query.key1;
var key2 = Request.Query.key2;
};
Where Query is DynamicDictionary.
Related Questions:
Get url parameters in NancyFx
Why are no query parameters being passed to my NancyFX module?
NancyFX: How do I check if query-string / form values have been correctly passed to my handler?

Router in backbone not handling route after initialization

I have multiple routers in my app, in general way it looks like this:
// Start backbone.js
if (!Backbone.History.started) {
Backbone.history.start({pushState: true, hashChange: false});
}
// Perform some RPC requests ...
// Depending on user role, received from the server should be created suitable router:
var router;
if (typeof app.user.role === 'manager') {
router = new routers.manager();
} else {
router = new routers.guest();
}
Problem is that after page is loaded and script is executed routers do not do. anything. They do not load route for current url automatically. So, i had to fix it this way (i am not sure that it is a right way):
routers.guest.initialize = routers.manager.initialize = function() {
var defaultRoute = 'default';
if (typeof this.routes[Backbone.history.fragment] !== 'undefined') {
this[this.routes[Backbone.history.fragment]]();
} else {
this.navigate(defaultRoute, true);
}
};
It is working fine, except one bug: when i use route with params, for example /reset-password-confirm/:code - it is unable to find in in routes property. I could write some more code to fix it, but i suppose that i am doing something wrong, if i have to write such things - as i understand router should handle routes just after it was created.
So, questions:
Why my router(s) does not handle routes for current url after it is being created? Perhaps i need to start backbone history later? (but this bug will happen again later then)
How it is possible to make routes with params like /user/:id work there?
Perhaps it is bad idea to re-create routers? Perhaps it is better to create all of them one time?
P.S. I've tried to create both routers and keep them, also i've trie to call backbone history start method after all routers were created.. but this didn't help :/
Assuming you route is declared as the following:
routes : {
'/user/:id' : 'user'
}
Your initialize code is not working because when you initialize your router with a url such as: /user/1234. Backbone.history.fragment will be /user/1234 (not /user/:id). Since the this.routes object doesn't have a key of /user/1234, your else clause calls the default route.
If you first instantiate your router then call Backbone.history.start(), you will be able to remove your router initialize code. When you navigate to a url as /user/1234 your router will match the /user/:id route and call the user function.
The following should work for you without adding your initialize code:
var router = (app.user.role === 'manager') ? new routers.manager()
: new routers.guest();
Backbone.history.start({pushState: true, hashChange: false});
Looking at the code, seems like you're starting the backbone history before initializing any routes. That's most likely not goning to work.
The correct way of doing this type of seperation is by creating all the routes based on the role received from the server and then start the backbone history. Here's an SO thread that talks about it with code samples as well : How to protect routes for different user groups

Resources