Im trying to figure out how to get my navigation bar setup as most of the UI is coming together. I have setup my index.js and also a Route.js and then linked them with my different components like so:
Index.js
import React from "react";
import ReactDOM from "react-dom";
import { Auth0Provider } from "./react-auth0-spa.js";
import { useAuth0 } from "./react-auth0-spa";
import Routes from "./Routes"
import config from "./utils/auth_config.json";
import { BrowserRouter } from "react-router-dom";
// A function that routes the user to the right place
// after login
const onRedirectCallback = appState => {
history.push(
appState && appState.targetUrl
? appState.targetUrl
: window.location.pathname
);
};
ReactDOM.render(
<Auth0Provider
domain={config.domain}
client_id={config.clientId}
redirect_uri={window.location.origin}
onRedirectCallback={onRedirectCallback}
>
<BrowserRouter>
<Routes />
</BrowserRouter>
</Auth0Provider>,
document.getElementById("root")
);
Routes.js
import React, { Component } from "react";
import { Router, Route, Switch, BrowserRouter } from "react-router-dom";
import {Link } from "react-router-dom";
import Profile from "./components/user/Profile";
import PrivateRoute from "./components/user/PrivateRoute";
import history from "./utils/history.js";
import HomePage from "./modules/HomePage.js";
import ProductPage from "./modules/ProductPage";
class Routes extends Component {
render() {
return (
<Router history={history}>
<Switch>
<Route path="/" component={HomePage} />
<Route path="/ProductPage" component={ProductPage} />
<PrivateRoute path="/profile" component={Profile} />
</Switch>
</Router>
)
}
}
export default Routes;
but when i reload my site it just continues to say localhost:8080/ProductPage like its suppose to be the default, then when i manually enter localhost:8080/ and click on a button after linking it with
<Link to="ProductPage">
it will show on the tab localhost:8080/ProductPage but wont actually redirect me to the other component, i am just wondering what i am doing wrong?
Issue
You have your "home" route listed first in the Switch.
Switch
Renders the first child <Route> or <Redirect> that matches the location.
"/" is less specific and matches basically all routes, so even though the URL is "/ProductPage", "/" still matches it and HomePage is rendered.
Solution
Either move it after the other more specific routes or use the exact prop on it.
<Router history={history}>
<Switch>
<Route path="/ProductPage" component={ProductPage} />
<PrivateRoute path="/profile" component={Profile} />
<Route path="/" component={HomePage} />
</Switch>
</Router>
or
<Router history={history}>
<Switch>
<Route exact path="/" component={HomePage} />
<Route path="/ProductPage" component={ProductPage} />
<PrivateRoute path="/profile" component={Profile} />
</Switch>
</Router>
Related
app.js
import { BrowserRouter as Switch, Route } from "react-router-dom";
import Login from "./Pages/Login";
import ViewPurchaseOrders from "./Pages/purchases/ViewPurchaseOrders";
import ViewProductSelectionGrn from "./Pages/GRN Management/View.product.selection-grn";
import Error from "./Components/404page/Error";
function App() {
return (
<div>
<Switch>
<Route path="/" exact component={Login} />
<ProtectedRoute
exact
path="/confirm-purchase-orders"
component={ViewPurchaseOrders}
/>
<ProtectedRoute
exact
path="/grn-product-selections"
component={ViewProductSelectionGrn}
/>
<Route path="*">{Error}</Route>
</Switch>
</div>
);
}
export default App;
404 page is rendering everywhere like above attached picture. I need to fix it. I tried few ways but it doesn't work properly.
Issue
The issue here is that you've managed to import the BrowserRouter as a Switch, so the Switch is really just a plain old router and all routes are being inclusively matched and rendered, i.e. all matching routes are rendered. Routes rendering on path="*" will always be matched and rendered.
import {
BrowserRouter as Switch, // <-- whoopsies!
Route
} from "react-router-dom";
...
function App() {
return (
<div>
<Switch> // <-- BrowserRouter in disguise
<Route path="/" exact component={Login} />
<ProtectedRoute
exact
path="/confirm-purchase-orders"
component={ViewPurchaseOrders}
/>
<ProtectedRoute
exact
path="/grn-product-selections"
component={ViewProductSelectionGrn}
/>
<Route path="*">{Error}</Route> // <-- always rendered
</Switch>
</div>
);
}
Solution
Import the BrowserRouter as a Router, then import the Switch and continue to render the routes into it so they are exclusively matched and rendered, i.e. only one match.
Example:
import {
BrowserRouter as Router,
Switch,
Route
} from "react-router-dom";
...
function App() {
return (
<div>
<Router>
<Switch>
<ProtectedRoute
path="/confirm-purchase-orders"
component={ViewPurchaseOrders}
/>
<ProtectedRoute
path="/grn-product-selections"
component={ViewProductSelectionGrn}
/>
<Route path="/" component={Login} />
<Route path="*">{Error}</Route>
</Switch>
</Router>
</div>
);
}
I have just started with React and not able to get the router working. Below is the code for router. If I use the individual components without the router, they are displayed on the screen. But with router I don't get any text on the screen across any of the paths.
Please let me know if I am missing something. Below is the code:
import { Route } from 'react-router-dom';
import AllMeetupsPage from './pages/AllMeetups';
import NewMeetupPage from './pages/NewMeetup';
function App() {
return (
<div>
<Route path='/' exact>
<AllMeetupsPage />
</Route>
<Route path='/new-meetup'>
<NewMeetupPage />
</Route>
</div>);
}
export default App;
A route needs to be a descendent of router component. I'm not sure which version of react-router you're using, but this will be a BrowserRouter and Routes component for react-router v6 and on v4/v5 it'll be a BrowserRouter
Here's some examples:
v6:
import {
BrowserRouter,
Routes,
Route
} from "react-router-dom";
import AllMeetupsPage from './pages/AllMeetups';
import NewMeetupPage from './pages/NewMeetup';
function App() {
return (
<div>
<BrowserRouter>
<Routes>
<Route path="/" exact element={<AllMeetupsPage />}/>
<Route path="/new-meetup" element={<NewMeetupPage />}/>
</Routes>
</BrowserRouter>
</div>);
}
export default App;
You missed using Switch component
import { Route , Switch } from 'react-router-dom';
function App() {
return (
<div>
<Switch>
<Route path='/' exact>
<AllMeetupsPage />
</Route>
<Route path='/new-meetup'>
<NewMeetupPage />
</Route>
</Switch>
</div>);
}
export default App;
Hello guys so I'm trying to create a web app using react-bootstrap and use BrowserRouter to link each of the component I have. I already wrap the index JS with BrowserRouter and I already add the Switch and Route tag to the navigation component, but when I tried to implement the navigation into app.js the web start to load endlessly without showing anything. Can anyone please help me with it ?
here is my navigation code:
import React from 'react'
import Facilities from './Facilities'
import Room from './Room'
import Booking from './Booking'
import Contact from './Contact'
import App from '../App'
import { Route, Switch } from 'react-router-dom'
const Navigation = () => {
return (
<>
<Switch>
<Route path="/facilities">
<Facilities/>
</Route>
<Route path="/room">
<Room/>
</Route>
<Route path="/contactus">
<Contact/>
</Route>
<Route path="/bookingRoom">
<Booking/>
</Route>
<Route path="/">
<App/>
</Route>
</Switch>
</>
)
}
export default Navigation
If the App component is the default App component after creating a React app using npx create-react-app ... command, I suggest you not use another App name for other files in your project.
But if you want to use your Navigation component as the root component, you could try this:
Option 1:
index.js
import ReactDOM from "react-dom";
import Navigation from "./Navigation ";
const rootElement = document.getElementById("root");
ReactDOM.render(
<Navigation />,
rootElement
);
Navigation.js
import React from 'react'
import Facilities from './Facilities'
import Room from './Room'
import Booking from './Booking'
import Contact from './Contact'
import App from '../App'
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
const Navigation = () => {
return (
<Router>
<Switch>
<Route path="/facilities">
<Facilities/>
</Route>
<Route path="/room">
<Room/>
</Route>
<Route path="/contactus">
<Contact/>
</Route>
<Route path="/bookingRoom">
<Booking/>
</Route>
<Route path="/">
<App/>
</Route>
</Switch>
</Router>
)
}
export default Navigation
Option 2:
index.js: add BrowserRouter as Router from react-router-dom here
ReactDOM.render(
<Router>
<Navigation /> {/* put the Navigation component here */}
</Router>,
rootElement
);
Navigation.js: delete BrowserRouter as Router from react-router-dom here
return (
<Switch>
<Route path="/facilities">
<Facilities/>
</Route>
<Route path="/room">
<Room/>
</Route>
<Route path="/contactus">
<Contact/>
</Route>
<Route path="/bookingRoom">
<Booking/>
</Route>
<Route path="/">
<App/>
</Route>
</Switch>
)
Switch is not a link to a component, but a decision about what is to be rendered in this space.
Imagine it to be a (pseudo-code)
switch(path){
case "path1": route(Component1); break;
case "path2": route(Component2); break;
default: route("*"); break;
Therefore, put in the component (or at the highest level where you are branching based on path), and not navigation.
The way we have done (with react-bootstrap) in our apps is this way:
// App.js
import Navigation from "./Navigation";
import Facilities from "./Facilities" .. and so on
const App = ({}) => {
return
<Navigation />
<Switch>
<Route path="/facilities" component={Facilities}/>
<Route path="/rooms" component={Rooms}/>
</Switch>
}
// Navigation.js
import Link from "react-bootstrap/Link";
const Navigation = () => {
<div>
<Link to="/facilities"/>
<Link to="/rooms"/>
</div>
}
I have a simple question. What is the best way to use a navbar with multiple components using react router? Just let me show the code so you can understand what I'm trying to say.
import React from "react";
import "./App.css";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect
} from "react-router-dom";
import Auth from "./website/Auth/Auth";
import SocialMedia from "./website/SocialMedia/SocialMedia";
import SingleUser from "./website/SingleUser/SingleUser";
import Search from "./website/Search/Search";
import SinglePhoto from "./website/SinglePhoto/SinglePhoto";
import Navbar from "./components/Navbar/Navbar";
function App() {
const logIn = JSON.parse(localStorage.getItem("token"));
return (
<Router>
<Switch>
<Route exact path="/" component={Auth}>
{logIn ? <Redirect to={`/profile/${logIn.data.id}`} /> : <Auth />}
</Route>
<Navbar>
<Route exact path="/profile/:id" component={SingleUser} />
<Route exact path="/socialmedia" component={SocialMedia} />
<Route exact path="socialmedia/search" component={Search} />
<Route exact path="socialmedia/photo/:id" component={SinglePhoto} />
</Navbar>
</Switch>
</Router>
);
}
export default App;
So I have to reuse my Navbar component, and I tried to use <Navbar />, then the other routes below, but that wasn't working, and when I put <Navbar> </Navbar> that worked and the other components will appear, but is that the way I reuse my Navbar component?
Thanks for your time !!
import React from "react";
import "./App.css";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect
} from "react-router-dom";
import Auth from "./website/Auth/Auth";
import SocialMedia from "./website/SocialMedia/SocialMedia";
import SingleUser from "./website/SingleUser/SingleUser";
import Search from "./website/Search/Search";
import SinglePhoto from "./website/SinglePhoto/SinglePhoto";
import Navbar from "./components/Navbar/Navbar";
function App() {
const logIn = JSON.parse(localStorage.getItem("token"));
return (
<Router>
<Switch>
<Route exact path="/" component={Auth}>
{logIn ? <Redirect to={`/profile/${logIn.data.id}`} /> : <Auth />}
</Route>
<Route Component={Navbar}>
<Route exact path="/profile/:id" component={SingleUser} />
<Route exact path="/socialmedia" component={SocialMedia} />
<Route exact path="socialmedia/search" component={Search} />
<Route exact path="socialmedia/photo/:id" component={SinglePhoto} />
</Route>
</Switch>
</Router>
);
}
export default App;
Try this!
If you want the Navbar to render only on certain routes then render it only on certain routes. Render the Navbar into a route outside the Switch and specify all the paths you want it to be rendered on in an array on the path prop.
Additional notes:
Within the Switch component, order and path specificity matter, reorder your routes to specify more specific paths before less specific paths. This allows you to not need to specify the exact prop for every route.
Don't specify both a component prop and render children on a single Route, see Route render methods. Just render the Redirect or Auth component as children.
Code:
function App() {
const logIn = JSON.parse(localStorage.getItem("token"));
return (
<Router>
<Route
path={["/profile", "/socialmedia"]}
component={Navbar}
/>
<Switch>
<Route path="/profile/:id" component={SingleUser} />
<Route path="socialmedia/photo/:id" component={SinglePhoto} />
<Route path="socialmedia/search" component={Search} />
<Route path="/socialmedia" component={SocialMedia} />
<Route path="/">
{logIn ? <Redirect to={`/profile/${logIn.data.id}`} /> : <Auth />}
</Route>
</Switch>
</Router>
);
}
I'm having issues with my project, actually i'm trying to handle a 404 page when the user enters different url outside of the Routes in my App, but using my knowledge of React and react-router only needs to put the last route has no path and exact path wrapped by a Switch from react-router but not work well, the home page is rendering the Home and the NotFound components at same time.
I've tried to remove Container component inside the Router but that makes that all of the components after MenuBar disappears.
I've tried to put path='*' in the last Route having 2 components rendered in the same page.
A picture of what i'm talking about:
2 components at same time
My project have 3 principal files:
1.- Index.js :
import ReactDOM from 'react-dom';
import * as serviceWorker from './serviceWorker';
import ApolloProvider from './ApolloProvider';
import 'semantic-ui-css/semantic.min.css';
import 'animate.css/animate.min.css';
import './App.css';
ReactDOM.render(ApolloProvider, document.getElementById('root'));
serviceWorker.unregister();
2.- ApolloProvider.js (using Apollo with GraphQL) :
import React from 'react';
import App from './App';
import ApolloClient from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { createHttpLink } from 'apollo-link-http';
import { ApolloProvider } from '#apollo/react-hooks';
const httpLink = createHttpLink({
uri: 'http://localhost:5000/graphql'
});
const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache()
});
export default (
<ApolloProvider client={client}>
<App />
</ApolloProvider>
);
3.- And finally App.js :
import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { Container } from 'semantic-ui-react';
import MenuBar from './Components/MenuBar';
import Home from './Pages/Home';
import Login from './Pages/Login';
import Register from './Pages/Register';
import NotFound from './Pages/404';
const App = props => (
<Router>
<Switch>
<Container>
<MenuBar />
<Route exact path='/' component={Home} />
<Route exact path='/login' component={Login} />
<Route exact path='/register' component={Register} />
<Route path='*' component={NotFound} />
</Container>
</Switch>
</Router>
);
export default App;
I only need to render Home component when the user visits '/' but it's weird how react-router is rendering two components at same time, please le me know if you find where i'm wrong or a solution for that, i'll being posting updates if i find a solution or whatever.
Thanks in advance mates!.
Thanks to #skyboyer and #Hugo Dozois the issue was fixed, this is the updated App.js for future references:
const App = props => (
<Router>
<Container>
<MenuBar />
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/login' component={Login} />
<Route exact path='/register' component={Register} />
<Route path='*' component={NotFound} />
</Switch>
</Container>
</Router>
);
Best Regards!