I decided I need to stop using HasRouter, and instead, use BrowserRouter.
I switched out all my imports from:
import { HashRouter} from 'react-router-dom';
to
import { BrowserRouter } from 'react-router-dom';
As well as all my blocks:
<HashRouter>
to
<BrowserRouter>
My app nearly behaved as expected. All links in my app work fine.
For example:
<Link to={{pathname: `/budget/${item.id}`, state: params}}>{item.name}</Link>
Updated my URL as expected and navigates to the component.
My history works too:
handleEditRow(paymentNumber) {
this.props.history.push(`/schedule/${this.state.scheduleId}/event/${paymentNumber}`);
}
However, all my NavBar buttons fail. The URL updates as expected, but my app does not load the component:
I have my routes in :
return (
<Switch>
<Route exact path="/" component={Dashboard} />
<Route exact path="/accounts" component={Accounts} />
....
</Switch>
)
}
I'm assuming this works, as the links above are behaving.
In my NavBar, I just do simple links:
<Nav.Link as={NavLink} to='/accounts' exact>Accounts</Nav.Link>
I found a link that mentioned to use 'Link' instead of NavLink.
<Nav.Link as={Link} to='/accounts' exact>Accounts</Nav.Link>
But this still fails. URL updates, but page doesn't change.
As I say, the URL changes as expected, but the app does not load the app.
However, if I then select the URL in the address bar, and press Enter (Load the URL that it changed to), the app loads the correct component, as expected.
Can anyone spot my error?
It was working fine with HashRouter.
Just a quick tip: if you're not sure about which Router to use, you can import it aliased as "Router". You then don't have to change all HashRouter references to BrowserRouter if you decide to switch to another Router:
import { BrowserRouter as Router } from 'react-router-dom';
And then use:
<Router>
The advantage of this approach is that you only change the import and it works straight out of the box.
Related
I have configured routes using the React Router in the following way:
<Link to="/">
<Image src={logo} width="200"></Image>
</Link>
Where the above on click routes to the '/' path which is nothing but a Home Component.
Everything is working fine, except that, whenever there is QueryStringparameters, it is routing along with it.
Ideally it should be routed as: http://0.0.0.0:4321/#/
But it is routing as: http://0.0.0.0:4321/?foo=bar#/ keeping the queryParameter intact. I would like to remove this while routing. I am using HashRouter as a prinicipal Router in react.
And this is what I have tried so far:
<Link to="/" onClick={window.history.pushState({}, document.title, window.location.pathname)}>
<Image src={logo} width="200"></Image>
</Link>
But seems like it is not working, what would be the finest way to first remove the queryParameters then route to the Link?
Best practice is to use useHistory hook from 'react-router-dom'
const history = useHistory()
onClick={() => history.push('/')}
I am a beginner in ReactJS web development and I wanted to ask, how can I make multiple pages in ReactJS (for example if I click on a button called "About me" that it will redirect to a different part of the whole site, for example example.com/aboutme) without using react-dom-router?
I don't want to change much in the codes because I already use my App.js as the main page.
You should use your own router with react-router-dom to do this. I preferably use HashRouter.
(What is the difference between HashRouter and BrowserRouter in React?)
Here is a simple example for routing in App.js;
import { HashRouter as Router, Route, Switch } from 'react-router-dom';
// Components
import Homepage from './components/Homepage';
import AboutMe from './components/AboutMe';
import Error404 from './components/Error404';
export default function App() {
return (
<Router>
<Switch>
<Route key="homepage" exact path={['/', '/homepage']}>
<Homepage />
</Route>
<Route key="aboutme" exact path="/aboutme">
<AboutMe />
</Route>
<Route path="*">
<Error404 />
</Route>
</Switch>
</Router>
);
}
After that when you go /aboutme you will see AboutMe component or when you go / or /homepage you will see Homepage component. If you try to go /blabla like this you will see Error404 component.
For example in your render:
<div>
<ul>
<li onClick={this.onItemClick}>About me</li>
</ul>
</div>
Function that starts on click:
onItemClick: function () {
this.props.history.push("/about-me");
}
So, first I had an issue with the routes not working, but I resolved that with react-router-dom's "baseline" property, but now despite the home page loading, the subsequent links render beneath the first component, which is supposed to dissapear entirely when the link is clicked.
It works fine locally.
This is my app.js
import React from 'react';
import './App.css';
import Navbar from './Component/Navbar/Navbar';
import RecipeList from './Component/RecipeList/RecipeList';
import { Switch, Route, BrowserRouter } from 'react-router-dom'
import RecipeItemDetails from './Component/RecipeItemDetails/RecipeItemDetails';
function App() {
return (
<BrowserRouter basename={process.env.PUBLIC_URL}>
<div className="App">
<Navbar/>
<Route exact path="/" component={RecipeList} />
<Route path="/recipes/:id" component={RecipeItemDetails} />
</div>
</BrowserRouter>
);
}
export default App;
any ideas? I've tried adding "exact" to the second route which didnt work, and I've also tried wrapping the router in a "switch", but that doesnt work either. I'm stumped.
your routes are inside el. so the the re rendered part when the route change is the Route components , and the div and navbar not re-rendered this is the reason you see the new routes beneath the first component, you should do something like this
<BrowserRouter basename={process.env.PUBLIC_URL}>
<Route exact path="/" component={RecipeList} />
<Route path="/recipes/:id" component={RecipeItemDetails} />
</BrowserRouter>
and then in the RecipeList and RecipeItemDetails import the Navbar and enclose it in the desired
I am using react-router and having some difficulties with it's behaviour.
The Nav shows on all pages as desired. However, the Profile shows on all pages too. I only want to show this on /home and also on the /music and /players pages, which it does. However, it also shows on the /charts page which is confusing me.
My code looks like the following.
import React from 'react';
import { Route } from 'react-router-dom'
import Nav from './components/Nav'
import Profile from './components/Profile'
import Players from './components/Players'
import Music from './components/Music'
import Charts from './components/Charts'
const App = () => {
return (
<section>
<Nav />
<Route path="/home">
<div>
<Profile avatarUrl={ avatarUrl }/>
<Route path="/players" component={Players}/>
<Route path="/music" component={Music}/>
</div>
</Route>
<Route path="/charts" component={Charts}/>
</section>
)
}
export default App;
I have read through the docs, tried putting in a Switch component, added exact to the home route but this leads to other unexpected behaviour.
Can anyone advise what I am doing wrong?
Thanks Pete!
Try this:
import React from 'react';
import { Route, BrowserRouter as Router } from 'react-router-dom'
import Nav from './components/Nav'
import Profile from './components/Profile'
import Players from './components/Players'
import Music from './components/Music'
import Charts from './components/Charts'
const Home = ({match}) => {
return (
<div>
<Profile avatarUrl={ avatarUrl }/>
<Route path=`${match.url}/players` component={Players}/>
<Route path=`${match.url}/music` component={Music}/>
</div>
);
};
const App = () => {
return (
<section>
<Nav />
<Router>
<Switch>
<Route path="/charts" exact={true} component={Charts}/>
<Route path="/home" component={Home} />
</Switch>
</Router>
</section>
)
}
export default App;
I haven't tested this, but this should work.
Assuming that you're using react-router v4, I don't know if you can actually use your home route in the way you've used it.
In the code above, Switch basically renders the first match between the routes specified under it. The exact keyword will ensure that only /charts path will display the Charts component.
The Home component will render in any path that starts with /home.
Now, for path /home/players, you'll see the Profile and the Players component, whereas for path /home/music, you'll see the other combination.
Hope this helps. :)
Edit:
Added Router to the code.
Edit:
Working code available here: https://codesandbox.io/s/8x9pql9m19
Change route on right hand side to:
/home
/home/players
/home/music
/charts
I have set up a basic react app with hash navigation. Problem is when I click on any link to navigate between pages, I see that the hash in the url is changing properly, as well as I added a console.log in my layour's render to see if it's getting called and it is, with proper this.props.children values, however the page is not rendering anything. If I go to any route and refresh the page I see the correct components rendered, but if I navigate somewhere from there noting gets rendered until I refresh again.
import React from "react";
import ReactDOM from "react-dom";
import { IndexRoute, Router, Route, Link, hashHistory as history } from 'react-router';
class Layout extends React.Component {
render() {
console.log(this.props, document.location.hash);
return <div>
<div>
<span>LEYAUTI MLEAYTI {Math.random()}</span>
</div>
<div>
{this.props.children}
</div>
<div>
{this.props.params.project}
</div>
</div>
}
}
class CreateProject extends React.Component {
render() {
return <div>
<h1>Create PROEKT</h1>
</div>
}
}
class Projects extends React.Component {
render() {
return <div>
<h1>PROEKTI MROEKTI</h1>
<Link to="/projects/create">New project</Link>
</div>
}
}
ReactDOM.render(
<Router history={history}>
<Route path="/" component={Layout}>
<IndexRoute component={Projects}/>
<Route path="projects/create" component={CreateProject}/>
</Route>
</Router>,
document.getElementById('app-root'));
Here is a visual of what's happening in the console when I navigate on a couple routes, but the DOM remains unchanged
This may be an issue with hashHistory. Which react-router version are you using? With v4 and above, you need to use history like so -
import createHistory from 'history/createHashHistory'
const history = createHistory()
// pass history to the Router....
Your component didn't actually unmount/remount if you only update your hashtag in your url. The route however, is updated. So you can only see the component loads content for once when you refresh the page.
You will need to create state variables and update it in a routeChange handler callback and bind the updated state variable to your view by using setState. Then the component can get updated.
See this post for how to add the route change listener (https://github.com/ReactTraining/react-router/issues/3554)
Alright, so I got down to the bottom of it.
The problem was that I was including my client.min.js file before the default app.js file of laravel 5.4's default layout. For some reason it broke react in a very weird way. What I had to do is switch the order in which the two files were included.