React-Router Questions/Issues - javascript

I've decided to use React-Router to manage the routing of my Meteor JS App that uses REACT JS.
I've gotten React-Router to work 'somehow', but it is having some negative side effects that I would like to explain here, in the hopes of finding a solution.
First of all, here is my code:
if (Meteor.isClient) {
Meteor.startup(function () {
console.log('startup');
Hooks.init();
const {Router, Route} = ReactRouter;
const history = ReactRouter.history.useQueries(ReactRouter.history.createHistory)()
React.render((
<Router >
<Route name="home" path="/" component={Sidebar}>
<Route name="managedata" path="managedata" component={ManageData} />
</Route>
</Router>
), document.getElementById("render-target"));
});
}
and in order to navigate between those two routes I've used the Link component provided by React-Router:
<ReactRouter.Link className="item" to="/">
<i className="home icon"></i>
EXAMPLE
</ReactRouter.Link>
<ReactRouter.Link className="item" to="managedata">
<i className="block layout icon"></i>
Manage Data
</ReactRouter.Link>
This is the problem:
1.) Upon loading of the homepage which has the "/" as the path, I am getting random characters showing the URL. This is ugly especially since one would only expect "/" or just nothing to show in the url aside from the domain name or localhost....
e.g. http://localhost:3000/#/?_k=q2c52z
2.) When I click on the Link to 'managedata' I am also getting some random characters in the URL
e.g. http://localhost:3000/#/managedata?_k=6clzfn
Here are my questions:
1.) What is causing those ugly characters to show up in the URL and how do I get rid of them?
2.) Does Link only use the path value? As you can see above, my homepage has a name "home" but a path of "/", I've noticed that if I change the Link to Link to="home" then I get directed to a URL with a "home" on the path which seems to be incorrect.
3.) I ended up using 'component' above as one of the props in Route. I've noticed that many of the examples on the internet uses 'handler'. However, when I use 'handler' in my code.....it doesn't work.....
How are those different?
4.) I've defined my routes as above, but when I use the page does not render initially, but if I click back button on the browser and then click the forward button, then it renders. How do I solve this?

Many hours ago I had the above problems.
Now I've found the solution and I'd like to post it here in the hopes of saving some time for future readers who bump into the same problem.
Here is the Q and A:
1.) What is causing those ugly characters to show up in the URL and how do I get rid of them?
As per https://github.com/rackt/react-router/blob/master/UPGRADE_GUIDE.md
"If you do not specify a history type (as in the example above) then you will notice some unusual behaviour after updating to 1.0.0. With the default hash based routing a querystring entry not defined by yourself will start appearing in your URLs called "_k". An example of how it looks is this: ?_k=umhx1s. "
So add 'history' into the Router.
e.g.
const {Router, Route, IndexRoute} = ReactRouter;
const history = ReactRouter.history.useQueries(ReactRouter.history.createHistory)()
React.render((
<Router history={history}>
<Route path="/" component={Sidebar}>
<IndexRoute component={Dashboard} />
<Route path="managedata" component={ManageData} />
</Route>
</Router>
), document.body);
Notice the history={history} inside the Router.
2.) Does Link only use the path value? As you can see above, my homepage has a name "home" but a path of "/", I've noticed that if I change the Link to Link to="home" then I get directed to a URL with a "home" on the path which seems to be incorrect.
After reading and experimenting....
The value of 'to' should be the path.
Not only should it be the path, it should be the path surrounded by {}.
For example, for the route defined above the Link should be used like this:
<Link to={"/"} className="item" >
<i className="home icon"></i>
EXAMPLE
</Link>
<Link to={"/managedata"} className="item" >
<i className="block layout icon"></i>
Manage Data
</Link>
The surrounding {} made an important difference for me.
Otherwise the page would not render initially....I had to click back and forward again on the browser for the page to render.
3.) I ended up using 'component' above as one of the props in Route. I've noticed that many of the examples on the internet uses 'handler'. However, when I use 'handler' in my code.....it doesn't work..... How are those different?
https://github.com/rackt/react-router/blob/master/UPGRADE_GUIDE.md
Based on the above link, it is the difference between the old API and the new API.
4.) I've defined my routes as above, but when I use the page does not render initially, but if I click back button on the browser and then click the forward button, then it renders. How do I solve this?
I've answered this problem in the answer to number 2.).
But basically, for me, I added {} around the path and it started to render properly.
e.g.
<Link to={"/managedata"} className="item" >
<i className="block layout icon"></i>
Manage Data
</Link>

Related

react-router-dom: clicking on Link adds the route to the Url indefinately

Basically, if I click on one of the navbar links, i.e. hotmelt, pressureSensitive, liquids.
http://localhost:3000/hotmelt ,
http://localhost:3000/pressure-sensitive ,
http://localhost:3000/liquid
Then click one of the types of adhesives listed under one of those pages, ie fg3000
http://localhost:3000/pressure-sensitive/fg3000
it shows the item clicked. BUT, when I click on another navbar link,
i.e. hotmelt,
instead of removing the pressure-sensitive/fg3000 and looking like this: http://localhost:3000/hotmelt
I get this: http://localhost:3000/pressure-sensitive/hotmelt
so I have one navlink path sitting in front of the other in the url, thus not showing anything on the page.
the only fix i have currently, is using the back button in the browser. and that lets the url follow the logical order.
I'm assuming I'm using a reusable component as a variable link in a way that maybe is causing the issue.
here's app.js
<Route exact path="/hotmelt" component={Hotmelt} />
<Route exact path="/hotmelt/:id" component={SingleAdhesive} />
<Route exact path="/liquid" component={Liquid} />
<Route exact path="/liquid/:id" component={SingleAdhesive} />
<Route exact path="/pressure-sensitive" component={PressureSensitive} />
<Route exact path="/pressure-sensitive/:id" component={SingleAdhesive} />
Notice how SingleAdhesives is used multiple times. Depending on one of three different adhesives. I have a feeling that's mixing things up? I'm just not sure how else to go about it?
Here's my git repo for this web app
Thank you for your thoughts/comments!
I was doubting in the answer so I downloaded the repo to test it. On your navbar component, your Link's components have something like this:
<Link to="hotmelt" className="nav-link text-white" >Hot Melt<span className="sr-only"></span></Link>
Just add a / before the hotmelt like this:
<Link to="/hotmelt" className="nav-link text-white" >Hot Melt<span className="sr-only"></span></Link>
...and it will work fine!

Why is this React Router redirect not working? How to make it work?

Why is the following React Router redirect not working? How can I make it work?
<div>
<Route path = "/" exact component = {Slideshow} />
<Route path = "/favourite-movies/1" exact component = {TopMovies} />
<Redirect from = "/film/abc/:id" to ="/film/:id" />
<Route path = "/film/:id" exact component = {Film} />
</div>
Let me elucidate my intention. The favourite movies section contains some elements which link to /film/:id, (dynamically). Say id = 100. In film/100 page , I have a list of recommended movies, which in turn also links to /film/:id. When I am directly calling say film/50 from film/100 page, even though the url changes to film/50, the content remains the same. Then I refresh the page which results in the contents of film/50 being rendered.
To prevent this I am calling film/abc/50 from film/100. I want to redirect the film/abc/50 page to film/50 page. Is this a feasible solution of the problem? How can I solve this problem? Please clarify.
Each Route in React-Router must be child of Switch or Router.
Do you have your Route in Switch or Router component placed?

The <Link> from react-router-dom does not change the URL

I am currently in process of making a website, and hit a wall on this. I am using react-router-dom for routing my app, and kinda new to it, but in one page, the link that I put on the page does not change the URL
I already tried on previous component, in which I put the button on one component, then use the Link to load another component based on the Link and Route given. However, on this one, despite using similar structure as before, does not work at all
This is the code for the page that loads. I already imported the BrowserRouter as Link from react-router-dom
<div>
<p>TEST</p>
<Link to="/leadslist"><button class="btn btn-success">Back to Leads List</button></Link>
</div>
This is the target page
<div>
<Router>
<Switch>
<Redirect from="/leads" to="/leadslist" />
<Route path="/leadsForm" component={LeadsForm} />
<Route path="/leadslist" component={LeadsList} />
<Route path="/leaddetails" component={LeadsDetails}/>
</Switch>
</Router>
</div>
my previous try clicking button from "/leadslist" to "/leadsForm" actually worked, but then I try to load to "leaddetails" to try to go back to "/leadslist", but it doesn't change the URL at all. Any help will be truly appreciated.
You should not be importing BrowserRoute as Link from the react-router-dom. Both are different things. You need to import Link directly from react-router-dom. Rest, it should work solid.
You should be importing link this way:
import { Link } from "react-router-dom";
Now, I am not sure what's exactly happening your app. But here, I have created a very basic demo or working react-router using CodeSandBox. You can take a look, it should help you fix the problem you are having.
Also, you can read this article to further understand the working of the react router.
Your code doesn't work because you have added button inside Link tag so on click of button React only fires onClick method of button and Link will no be clicked!
So in solution, you can remove a button from Link tag
<Link to="/leadslist">Back to Leads List</Link>
or You can use Below solution,
Instead of adding button in Link You should do this,
import withRouter from 'react-router-dom'
const Component = (props) => {
<div>
<Button onClick={()=>props.history.push('/leadslist')}
</div>
}
export default withRouter(Component)
Add HOC withRouter to your component and you can get history object in prop.

React Router - undefined params if previous one is not defined

This is how my routing looks like:
<Switch>
...
<Route
path="/search/:searchValue/:who?/:industries?/:area?"
component={Search}
/>
...
</Switch>
Then I've this link (in another component)
<NavLink
className={classes.appBarLink}
to={`/search/${input}/${chiCerco}/${industriesSel}/${geoArea}`}
>
I'm filling those data in to="" with a form.
In the next page I'm catching the data with:
this.props.match.params.who ... and so on.
Problem is, if "industries" is empty I'm not ablet to get "area".
So I've to fill all the data, all the time.
Is It correct?
The params are actually "optionals" in the URL.
(also the URL from this.props.match.url is incomplete if I'm not filling all)
Thanks a lot.

react router relative link does not link properly

So I'm using the npm package react-router-relative (https://www.npmjs.com/package/react-router-relative) but it doesn't seem to be switching the url properly.
Here's what my links looks like:
<Link to='items' className="btn btn-default submission-button">Items</Link>
<Link to='maps' className="btn btn-default submission-button">Maps</Link>
Here's my routing:
<Route path="submissions" component={SubmissionPage}>
<Route path="items" component={ItemSubmissions}></Route>
<Route path="maps" component={MapSubmissions}></Route>
</Route>
what happens is the first time I click on the link it'll link properly i.e.
http://localhost:3000/#/account/submissions/items
but when I hit it again it'll go to:
http://localhost:3000/#/account/submissions/items/items
at this point the end part will switch rather than append, but throws an error.
However, I'm trying to make the part right after 'submission' switch, i.e. account/submissions/items account/submissions/maps.
What am I doing wrong?
I've tried a non-relative link variation of this, i.e. {this.props.location.pathname + '/items'} but it just does the same thing.
First, let's emphasis on the concept of relative link.
It is a link that will bring you somewhere depending on where you already are.
Meaning, result will vary if you use the same relative link in different places (URLs). The direct implication is that if you want only one given behaviour for a relative link, you cannot use it at several places.
What happens in your case is that the same relative link appears for different URLs, leading to different results.
What can you do:
As pointed earlier, you could use currentPath props, suggested in the page you linked here.
The result would be something like:
<Link to='items' currentPath='/submissions'>Items</Link>
<Link to='maps' currentPath='/submissions'>Maps</Link>
Which looks like a disguised absolute path:
<Link to='/submissions/items'>Items</Link>
<Link to='/submissions/maps'>Maps</Link>
A solution for relative paths would be:
<Link to='../items'>Items</Link>
<Link to='../maps'>Maps</Link>
But keep in mind that those links, being relative, should only be displayed in one place, in your case #/submissions/somewhere
If you want a link that brings you to the same page regardless of the current location, you should use absolute links.
So far, I haven't come up with many uses for relative links.
Go back: <Link to="..">Go back</Link>
Or maybe common actions: <Link to="./edit">Edit</Link>
To conclude, I would say that there is no need for relative links when only one behaviour is expected. One behaviour means one route, and if you know the route, you might as well use an absolute link. Relative links should be used only when you expect different behaviours.
I have searched for your problem and i found this useful package react-router-relative-links
To install it run in your terminal :
npm install react-router-relative-links react-router-apply-middleware
then in you routes file you will apply the middleware like so:
import { Router, Route, browserHistory } from 'react-router';
import applyMiddlewareRouter from 'react-router-apply-middleware'
import { useRelativeLinks } from 'react-router-relative-links'
<Router history={browserHistory} render={applyMiddlewareRouter(useRelativeLinks())}>
<Route path="submissions" component={SubmissionPage}>
<Route path="items" component={ItemSubmissions}></Route>
<Route path="maps" component={MapSubmissions}></Route>
</Route>
</Router>
then any time you you need to add a navigate Link you can add it like so:
we will assume the current path is localhost:8080/account/submissions
<RelativeLink to='./items'>test</RelativeLink> # to localhost:8080/account/submissions/items
<RelativeLink to='./maps'>test</RelativeLink> # to localhost:8080/account/submissions/maps
, However it's better to use the Link component provided by react-router
if you pass currentPath props to your link it will start work. otherwise, if you don't define the current path. it falls to window.location.hash which is not good.
<Link to='/items' currentPath='/submissions' className="btn btn-default submission-button">Items</Link>
<Link to='/maps' currentPath='/submissions' className="btn btn-default submission-button">Maps</Link>
I believe the npm package react-router-relative is a bit buggy.
personally, I don't recommend you to use in production.
I was not able to find any other approach but this. Unfortunately react-router doesn't support the relative paths but the work around would be using the Switch and then generating absolute paths in your components if it is suitable for your use. You have to update your react-router to 4+ before importing the Switch method.
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
<Router>
<Switch>
<Route path="submissions" component={SubmissionPage} />
<Route path="items" component={ItemSubmissions} />
<Route path="maps" component={MapSubmissions} />
</Switch>
</Router>
But probably if I were to use only two path as you are doing which ends up being /accounts/submissions/items and /maps I would probably just stick with the <Route path="/accounts/submissions/items" component={MapSubmissions} />
P.S : I am just pointing out my approach and solution. I am not sure whether it would cause other problems or not.

Categories