React Router <Link> changes URL but does not automatically render component [duplicate] - javascript

This question already has answers here:
Link tag inside BrowserRouter changes only the URL, but doesn't render the component
(2 answers)
Closed 7 months ago.
I'm attempting to use React Router to allow a button in my NavBar to change the view when a button is clicked. Specifically, I want an "Upload" button to change the URL to /upload and render the UploadPage component.
Currently, the URL will change, but the view does not automatically render, and the 'old' component is still visible. I need to manually reload the page or go to the URL directly for the view to load. How can I stop this behaviour so that it automatically renders without manual reload?
App.js:
import { Component } from "react";
import Home from "../src/components/Component/Home/Home";
import Header from "./components/Component/Header/Header";
import UploadPage from "./components/Component/VideoUpload/VideoUpload";
import { BrowserRouter, Switch, Route } from "react-router-dom";
class App extends Component {
render() {
return (
<BrowserRouter>
<Header />
<Switch>
<Route path="/" exact component={Home} />
<Route
path="/video/:videoId"
component={Home}
render={(routerProps) => <Home {...routerProps} />
/>
<Route path="/upload" component={UploadPage} />
</Switch>
</BrowserRouter>
);
}
}
export default App;
Header.js
(This is a snippet of just the button in the NavBar)
import { Link } from "react-router-dom";
const Header = () => {
return (
//NavBar code here...
<Link to="/upload">
<button>
<img draggable="false" src={uploadIcon} alt="upload-icon" />
UPLOAD
</button>
</Link>
);
};
VideoUpload.js
import React from "react";
const VideoUpload = () => {
return (
<section className="uploadContainer">
<section className="uploadContainer__titleContainer">
<h2 className="uploadContainer__title">Upload Video</h2>
</section>
</section>
);
};
export default VideoUpload;

After a lot of trial and error and research, I found that in my index.js:
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
Should be changed to:
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<BrowserRouter>
<App />
</BrowserRouter>
);
From my tests, <BroswerRouter> isn't necessary here and <App /> doesn't need to be wrapped for it to work, but, I'm keeping it wrapped just in case.
This fixes the issues I was experiencing.

Related

My app does not display in the browser when using React Router Dom [duplicate]

This question already has answers here:
React Router Dom routes are returning blank pages
(2 answers)
Closed 9 months ago.
My main App component does not display in the browser even though no error message is displayed.
Please assist
import React from 'react';
import {BrowserRouter as Routes,Route} from 'react-router-dom';
import MasterLayout from './layouts/admin/MasterLayout';
function App() {
return (
<div className="App">
<Routes>
<Route path="/admin/dashboard" component = {MasterLayout} />
</Routes>
</div>
);
}
export default App;
I don't understand why the App main component does not render on my webpage. There are no errors, but the web page is empty. Please assist me.
import React from "react";
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
import MasterLayout from './layouts/admin/MasterLayout';
const App = () => {
return (
<div className="app">
<Router>
<Routes>
<Route path="/admin/dashboard" element = {<MasterLayout/>} />
</Routes>
</Router>
</div>
);
};
export default App;
try this if it's not working check your imported MasterLayout
Seeing the code, you are not displaying any UI for main page or base router "localhost:3000/", only displaying in the "localhost:3000/admin/dashboard"
function App() {
return (
<div className="App">
<Routes>
<Route path="/admin/dashboard" component = {MasterLayout} />
</Routes>
</div>
)
}
In version 6 for react-router-dom, it should be element instead of component, and you should call the component (<MasterLayout/>), like so:
import React from 'react';
import {BrowserRouter as Routes,Route} from 'react-router-dom';
import MasterLayout from './layouts/admin/MasterLayout';
function App() {
return (
<div className="App">
<Routes>
<Route path="/admin/dashboard" element = {<MasterLayout/>} />
</Routes>
</div>
)
}

React Link element v5 not taking me to the desired page

I'm having trouble with this simple react routing. The problem is that after I click on "Go to invoices" or "Go to eshop", the URL changes, but the page content remains the same. It only changes if I am at localhost:1234/eshop (or /dashboard) and reload the page.
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
export default function App() {
return (
<Router>
<h1>Default layout</h1>
<Link to="/invoices">Go to invoices</Link>
<Link to="/eshop">Go to eshop</Link>
<Route path="/invoices">
<h2>Invoices page</h2>
</Route>
<Route path="/eshop">
<h2>eshop page</h2>
</Route>
</Router>
);
}
Any ideas how to fix this?
edit
sandbox here https://codesandbox.io/s/hungry-cloud-i2hui2?file=/src/App.js
It's a clash between React Router and StrictMode.
One possible solution is to place the Router outside of StricMode, in the index.js file itself:
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter as Router } from "react-router-dom";
import App from "./App";
const rootElement = document.getElementById("root");
const root = createRoot(rootElement);
root.render(
<Router>
<StrictMode>
<App />
</StrictMode>
</Router>
);
See: here and here
You should wrap your Route components with a Switch component.
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
export default function App() {
return (
<Router>
<h1>Default layout</h1>
<Link to="/invoices">Go to invoices</Link>
<Link to="/eshop">Go to eshop</Link>
<Switch>
<Route path="/invoices">
<h2>Invoices page</h2>
</Route>
<Route path="/eshop">
<h2>eshop page</h2>
</Route>
</Switch>
</Router>
)
}
https://v5.reactrouter.com/web/guides/quick-start

React Router Question: why history.push changes url but doesn't update component

Below is a sample code that renders two buttons (home and about) and two page component (also Home and About). Upon clicking each button, the buttons would call history.push to go to the respective page and should render the component.
However, what I notice is that when a button is clicked, the url changes but the component doesn't show up. I manage to get this fixed by passing the { forceRefresh: true } property when creating browser history like this const history = createBrowserHistory({ forceRefresh: true }); Still, I don't quite understand why this occur and why forceRefresh solves the problem and would appreciate any explanation.
That reason I didn't use the <Link> component to wrap around the button is because I want to call a function to execute something before redirecting when the button is clicked. If there is another way to do this, I would love to know from the community. Thanks.
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { createBrowserHistory } from 'history';
const MyApp = () => {
const history = createBrowserHistory();
return (
<Router history={history}>
<div>
<ul>
<li>
<button onClick={() => history.push('/')}>Home</button>
</li>
<li>
<button onClick={() => history.push('/about')}>About</button>
</li>
</ul>
<Switch>
<Route exact path='/'>
<Home />
</Route>
<Route exact path='/about'>
<About />
</Route>
</Switch>
</div>
</Router>
);
};
function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}
function About() {
return (
<div>
<h2>About</h2>
</div>
);
}
ReactDOM.render(<MyApp />, document.getElementById('root'));
This is because of this line:
const history = createBrowserHistory();
You are instantiating a history object which will be used by Router to keep track of the routing history. This is something used under the hood by Router and you shouldn't need to worry about it.
What you're doing wrong is to think that the history variable you declared there (use by Router) is the same used to navigate through the app. It's not.
You should use this history to navigate:
import { useHistory } from 'react-router-dom'
Usage:
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { createBrowserHistory } from 'history';
import { useHistory } from 'react-router-dom';
const MyApp = () => {
const historyInstance = createBrowserHistory();
const history = useHistory();
return (
<Router history={historyInstance}>
<div>
<ul>
<li>
<button onClick={() => history.push('/')}>Home</button>
</li>
<li>
<button onClick={() => history.push('/about')}>About</button>
</li>
</ul>
<Switch>
<Route exact path='/'>
<Home />
</Route>
<Route exact path='/about'>
<About />
</Route>
</Switch>
</div>
</Router>
);
};
And with that, everything should work

react-router link for route from another component

I have a React Component called ContentBar that holds a Route to display dynamic content:
//ContentBar.js
var React = require('react')
import ContentBarRoute from '../../../../routes/contentbar.routes'
const ContentBar = () =>
(
<ContentBarRoute />
)
export default ContentBar
I've placed this ContentBar in my root App structure:
//App.js
<div className="logBar">
<ErrorBoundary>
<Responsive minWidth={960}>
<ContentBar />
</Responsive>
</ErrorBoundary>
</div>
And I've created a route for a new menu in the ContentBarRoute component which I'm loading in the ContentBar:
//ContactBarRoute.react.js
const ContentBarRoute = () => (
<main>
<Switch>
<Route exact path="/logbar"component={LogBar}/>
<Route path="/user/:number/settings" />
<Route path="/user/:number/profile" />
<Route path="/user/add" component={UserAddMenu} />
</Switch>
</main>
)
When I try to link to /user/add from another component though, I'm not able to update the route from another component:
//Contactlist.react.js
<div className="contact-list useradd">
<Button as={Link} to="/user/add" className="btn-useradd">
<FontAwesome className="icon-adduser" tag="i" name="plus" />
</Button>
</div>
Can someone help me see what I'm doing wrong here? There's not a lot of information about routing between components, I found one answer in my research but it was slightly different: React-Router-4 routing from another component
The problem is that my routes and links are in separate areas of the hierarchy, whereas that guy's components were all close together.
Update:
The other example doesn't talk about rendering new components in place of old ones where one component is totally separate from the other:
Here is my router definition it exists in the class that sends the App to the html div:
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
//import { createStore } from 'redux'
import { HashRouter } from 'react-router-dom'
import configureStore from '../tools/store.enhancer';
import App from '../javascripts/entry';
//import rootReducer from '../app/reducers/index'
//let store = createStore(rootReducer)
const store = configureStore();
render((
<Provider store={store}>
<HashRouter>
<App />
</HashRouter>
</Provider>
), document.getElementById('root'));
The behavior I expect is that the existing component is switched out for the user-add component, but the actual behavior is that nothing happens when I click the button, and I get an error saying
Hash history cannot PUSH the same path; a new entry will not be added to the history stack

React Router Component not Rendering

I've been working with React Router and trying to route my App.js and Car.js components together. I wrote {this.props.children} in those two components but it still isn't working. There is no where on my local host page that shows any indication of the Car.js component when I deploy my app.
Here's my App.js:
import React, { Component } from 'react';
import Login from './Login.js';
import Search from './Search.js';
import Message from './Message.js';
import Car from './Car.js';
import {BrowserRouter, Route} from 'react-router-dom';
export default class App extends React.Component {
render() {
return (
<div>
<Login />
<Search />
<Message />
<div>
<BrowserRouter>
<Route path="/Car" component={Car}/>
</BrowserRouter>
{this.props.children}
</div>
</div>
);
}
}
Car.js:
// Car page example
import React, { Component } from 'react';
import {Router, Route} from 'react-router';
class Car extends Component {
render(){
return(
<div>
<h1> Cars page </h1>
{this.props.children}
</div>
);
}
}
export default Car;
So you're going to want at least 2 routes unless /Cars is the only page in which case you don't need routing! :)
In this example the Home component will be displayed when your url is something like http:/www.exmaple.com/
The Cars component will be displayed when the url is http:/www.exmaple.com/Cars
const App = () => (
<div>
<Login />
<Search />
<Message />
<div>
<BrowserRouter>
// you're going to want a default view
<Route exact path="/" component={Home} />
// this will be displayed when your url has /Car at the end of it
<Route path="/Car" component={Car} />
</BrowserRouter>
</div>
</div>
);
If you don't want to have to manually type in the urls to change the views... You will have to include a <Link /> or a <NavLink /> that points to the respective view.
Try <NavLink to="/Cars" /> and don't forget to add { ... NavLink ... } from "react-router-dom" as well.
You might want to have a look at react-router WEB documentation over at ReactTraining.com's react-router page. They're the people who created and maintain react-router. Good documentation as well!

Categories