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

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.

Related

React Router Linking using <button>

I am using React Router.
I want when the user clicks on the button, it directs them to the page (endpoint) /form which has the UserForm component.
Here is my code wrapping the button:
<Router>
<Link to="/form" className="updateLink">
<button className="updateBtn" onClick={() => {
this.update(id);
console.log(`Item Number: ${id} Was Updated Successfully`);
window.alert(`Item Number: ${id} Was Updated Successfully`);
}}>U</button>
</Link>
<Switch>
<Router exact path="/form" component={UserForm} />
</Switch>
</Router>
So the reason that doesn't work is because the Button has its own click handler separate from the link handler. You have two options available to you:
Style the Link tag such that it looks like a button but don't actually look like a button (this won't work if you need to do additional logic in addition to routing)
Actually use a button. And then use the 'useHistory' React Hook React Router provides to get the functionality you're looking for.
The component would look something like this:
const history = useHistory()
return (
<Button onClick={() => history.push("/abc")}/>
)
I would personally recommend that you simply style the link tag in the way that you need it to. As that would be more accessible and understandable to the user. But that's only a good idea if you only care about the routing.
Is the above code accurate as in your code?
Router statement should be set up as below, usually in App.js
<Router>
<Switch>
<Route path = './form' component = {form}
</Switch>
</Router>
You then create the form component and to link to it you then import the link component in the component you wish to use it.
Then use as below
<Link to = './form'> Some Text </Link>
Onto the button issue you are having
It will render but you shouldn't nest an <a> or <button> tag in HTML as it wont be sematic for screenreaders, isn't accessible, nor it it valid HTML.
The Link element in react creates and renders an <a> tag which shouldn't be nested in a button.
You could use useHistory in your case for the same effect
import React from 'react'
import { useHistory } from 'react-router-dom'
const component = () => {
const { push } = useHistory()
...
<button
type="button"
onClick={() => push('/form')}>
Click me to go to a form!
</button>
...
}

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?

React: Passing Props from grandparent to grandchild

I have a problem with passing props in react. This is my folder structure:
src
Component
Button.js
Container
PageContainer.js
Page
Page.js
I am using Bootstrap 4 to create a Button within Button.js:
<div>
<a className="btn btn-primary sharp" href={this.props.url} role="button">{this.props.btnName}</a>
</div>
There is nothing else in the class Button. So now I put a Button into the class PageContainer:
<div>
<Header/>
<Button url={this.props.urlBack} btnName="Back"/>
<Button url={this.props.urlNext} btnName="Next"/>
</div>
As you can see I passed a title to the buttons: Back and Next. That works fine. I could now add an url and it would work fine, but that's not what I want.
I added the PageContainer to the class Page such that I can add an url at this level:
<div>
<PageContainer urlBack="/" urlNext="/nextPage"/>
</div>
For some reason this is not working. Can someone explain me how I can pass props from grandparent to grandchild? In the documentation it says that this is the way how to do it. I also get no error, because the prop is not passed from Page to PageContainer. A console.log(this.props.urlBack) results in undefined.
PS: Maybe you asking why I am using the Page.js or for what reason do I have the PageContainer. First: There are far more components, I just left them out. Second: I wanna reuse the PageContainer for several pages such that I just have to change the url.
It doesn't look like you are passing props to your <VideoContainer /> component. You are merely assigning it as a routed component <Route />
Your answer can be found here:
React react-router-dom pass props to component
i.e.
<Route path="/algorithmus/bubblesort/video"
render={(props) => <VideoContainer {...props} />}
/>
However, I don't think this will get your your this.props.url and this.props.btnName. this.props.path, yes ..but you may have to revisit some logic there.
UPDATE:
After reading your comment and checking your repo, it doesn't look like there's anything wrong with your setup. I have emulated your BubblesortVideo -> VideoContainer hierarchy at the following:
https://stackblitz.com/edit/react-eaqmua

How to add both a header.html and a footer.html to all your routes when using singlepage?

We currently have a header.html and a footer.html that we include in our base.html that is loaded in the / route of our website. We're using a single page design and thus we don't reload base.html at any time other than when initially loading the page. In base.html we have a div with an id that we use to load all our html content with jQuery to. The problem we're facing now is that fact that accessing a route directly bypasses the load of header, and thus our jQuesry-scripts and bootstrap etc., and then the page looks like crap and doesn't work properly.
We figured we could remove the visual URL-change completely and use madeup route-names in our routes instead. But that feels like an overly complicated and not neccessarily secure way of doing it.
Ideally we would like to be able to know if the request is not coming from where it's supposed to.
Any ideas of how this can be accomplished? Or do you generally just expect no one to go to /signup on their own?
I use a Nav component which renders the "chrome" around the page.
export class Nav extends Component {
render = () => {
return (
<div>
<rb.Navbar>
<rb.Navbar.Header>
<rb.Navbar.Brand>
aktai
</rb.Navbar.Brand>
</rb.Navbar.Header>
</rb.Navbar>
{this.props.children}
</div>)
}
}
I mount it to all routes in React Router:
const router = (
<Router history={browserHistory}>
<Route component={Nav}>
<Route path="/folders" component={Folders}/>
</Route>
</Router>
)
You can also call it like:
<Nav>
<h1>welcome to my site</h1>
This is a place
</Nav>
Any component which renders this.props.children will work like that.

React-Router Questions/Issues

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>

Categories