I was trying to include a dynamic link using react-router-dom paths params e.g. (paths:"/link/:params"). But somehow any requests to such links returns a 404 error. Note the third route.
import React from 'react'
import { BrowserRouter, Switch, Route } from 'react-router-dom'
const EditExpensePage = (props) => {
return (
<div>
<p>EditExpense Page with id of {props.match.params.id}</p>
</div>
)
}
const AppRouter = () => (
<BrowserRouter>
<div>
<Header/>
<Switch>
<Route path="/" component={DashboardPage} exact={true}/>
<Route path="/create/" component={AddExpensePage}/>
<Route path="/edit/:id" component={EditExpensePage}/>
<Route path="/help" component={HelpPage}/>
<Route component={NotFoundPage}/>
</Switch>
</div>
</BrowserRouter>
)
export default AppRouter;
When I tried to visit the link eg.(localhost:8080/edit/43), i got a blank page with a log in the console which came from my bundled js file:
GET http://localhost:8081/edit/scripts/app.js 404 (Not Found)
Related
I am using react router for a SPA Dashboard. I have these two routes(Routes.js) in dashboard right now. Also, a separate route in App.js for landing page.
Now it works fine as expected when it loads and when I click different routes. For example, When I click customers route(in sidebar), it open the customers section on the same page in right side. But, when I refresh the customers page localhost:5000/customers, now it opens as a separate page. How can I solve this.
I tried debugging it but still no luck.
Here's an example : https://github.com/gouravthakur39/MRE
Unfortunately can't reproduce it in code sandbox
Routes.js
import React from "react";
import { Route, Switch } from "react-router-dom";
import Dashboard from "../pages/Dashboard";
import Customers from "../pages/Customers";
const Routes = () => {
return (
<Switch>
<Route path="/home" exact component={Dashboard} />
<Route path="/customers" exact component={Customers} />
</Switch>
);
};
export default Routes;
Part of App.js
import { Fragment } from "react";
import { BrowserRouter, Switch, Route } from "react-router-dom";
import PrivateRoute from "./private/PrivateRoute";
import Landing from "./pages/Landing";
import Home from "./pages/Home";
import Customers from "./pages/Customers";
function App() {
return (
<Fragment>
<div className="App">
<BrowserRouter>
<Switch>
<Route exact path="/" component={Landing} />
<PrivateRoute exact path="/home" component={Home} />
<PrivateRoute exact path="/customers" component={Customers} />
</Switch>
</BrowserRouter>
</div>
</Fragment>
);
}
export default App;
Question/Issue
Based on your code and the description on the Dashboard component it sounds like you want Dashboard and Customers to render "nested" in the "/home" path.
const Dashboard = () => {
return (
<div>
<h1>Dashboard</h1>
<p>I want to open dashboard and customers here when clicked</p>
<p>
Right now, when you click customers, it will open it in new page and not
here.
</p>
</div>
);
};
This is because Home is rendering the Dashboard on the same "/home" path, and the sidebar is linking to a "/customers" path at the root router level. This Customers component is outside the nested home/dashboard component.
Solution
App
For this the root "/home" in App needs to not exactly match in order for it to render nested routes. Remember also that in the Switch component that path order and specificity matter. Order the paths from more specific to less specific, i.e. "/home" is more specific than "/" and should be ordered higher/before. The "/customers" route/path should be removed since it will be rendered by Home.
function App() {
return (
<Fragment>
<BrowserRouter>
<Switch>
<Route path="/home" component={Home} />
<Route path="/" component={Landing} />
</Switch>
</BrowserRouter>
</Fragment>
);
}
Routes (rendered by Home)
Use the useRouteMatch hook to gather the current matched path value and build the nested routes. Remember the path order and specificity rule for the Switch.
import { Route, Switch, useRouteMatch } from "react-router-dom";
const Routes = () => {
const { path } = useRouteMatch();
return (
<Switch>
<Route path={`${path}/customers`} component={Customers} /> // "/home/customers"
<Route path={path} component={Dashboard} /> // "/home"
</Switch>
);
};
Sidebar (rendered by Home)
Use the useRouteMatch hook to gather the current matched url value and build the nested links.
import { Link, useRouteMatch } from "react-router-dom";
const Sidebar = () => {
const { url } = useRouteMatch();
return (
<div>
<ul>
<li>
<Link to={url}>Dashboard</Link> // to "/home"
</li>
<li>
<Link to={`${url}/customers`}>Customers</Link> // to "/home/customers"
</li>
</ul>
</div>
);
};
This question already has answers here:
React Router works only after refreshing the page
(5 answers)
Closed 1 year ago.
I'm new to react & react router dom v5, also my english is bad. Thank you in advance for helping me.
my problem:
I have 2 Main Routes in my App.js route
import { Suspense } from 'react';
import {BrowserRouter as Router, Switch, Route} from 'react-router-dom'
/* Pges */
import AdminContainer from './Pages/Admin/AdminContainer';
import PublicContainer from './Pages/Public/PublicContainer';
import NotFound from './Pages/NotFound'
import AuthContainer from './Pages/Auth/AuthContainer';
/* Protected Route */
/* Helpers */
function App() {
console.log("APP")
return (
<Suspense fallback={(<p>Loading</p>)}>
<Router>
<Switch>
<Route path="/auth" component={AuthContainer} />
<Route path="/admin" component={AdminContainer} />
<Route path="/*" component={PublicContainer} />
<Route path="*" component={NotFound} />
</Switch>
</Router>
</Suspense>
)
}
export default App;
the authcontainer have 2 sub routes
"/signin"
"/signup"
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
withRouter
} from "react-router-dom";
// PAGES
import Signin from "../Auth/Signin";
import Signup from "../Auth/Signup";
const AuthContainer = () => {
console.log("AUTH")
return (
<div>
<Router>
<Switch>
<Route exact path="/auth" component={Signin}/>
<Route exact path="/auth/signin" component={Signin}/>
<Route exact path="/auth/signup" component={Signup}/>
</Switch>
</Router>
</div>
);
};
export default withRouter(AuthContainer);
then the my publiccontainer have 3 sub routes
"/"
"/product"
"/mycart"
/* Dependencies */
import { Route, Switch, BrowserRouter as Router } from 'react-router-dom'
/* Components */
import Header from "../../Components/Header"
import Products from "./Products"
import Home from "./Home"
import UserProfile from "../User/AccountProfile"
import MyCart from '../Public/MyCart'
const PublicContainer = () => {
console.log("PUBLIC")
return (
<div>
<Router>
<Header />
<Switch>
<Route exact path='/' render={(props) => <Home />} />
<Route exact path='/products' render={(props) => <Products />} />
<Route exact path='/mycart' render={(props) => <MyCart isAuth={false} />} />
</Switch>
</Router>
</div>
)
}
export default PublicContainer
the my cart component will only render if isAuth is true, else it will redirect to "/auth/signin"
import React from 'react'
import { Redirect } from 'react-router'
const MyCart = ({isAuth}) => {
if(!isAuth)
return (<Redirect from='*' to='/auth/signin'></Redirect>)
return (
<div>
my cart
</div>
)
}
export default MyCart
The problem is, its trying to redirect to "/auth/signin" but it is still in the "/" page
When i hit reload it finally redirect to "/auth/signin"
How can i fix this issue, I really appreciate your help
UPDATE
this is overview of my planned routes
By the way i think when the mycart isAuth is false then it tries to Link to /auth/signin which causes the link in the top url to correctly point to auth signin, but after that it only checks the subroutes of the publiccontainer instead of checking the app.js routes
But when i reload it, it start searching the correct route from the app.js routes which return the expected route & page which is the sign in
I read a almost similar question in terms of only rendering the correct path when hitting refresh/reload
here React Router works only after refreshing the page
The problem was i'm wrapping the sub routes with a new router, so i tried removing the Router jsx that is wrapping the Switch> & other subroutes in both AuthContainer.js & PublicContainer.js
this is the updated AuthContainer.js
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
withRouter
} from "react-router-dom";
// PAGES
import Signin from "../Auth/Signin";
import Signup from "../Auth/Signup";
const AuthContainer = () => {
console.log("AUTH")
return (
<div>
<Switch>
<Route exact path="/auth/signin" component={Signin}/>
<Route exact path="/auth/signup" component={Signup}/>
<Route exact path="/auth" component={Signin}/>
</Switch>
</div>
);
};
export default withRouter(AuthContainer);
And this is the PublicContainer.js
/* Dependencies */
import { Route, Switch } from 'react-router-dom'
/* Components */
import Header from "../../Components/Header"
import Products from "./Products"
import Home from "./Home"
import UserProfile from "../User/AccountProfile"
import MyCart from '../Public/MyCart'
/* Protected */
const PublicContainer = ({toAuth}) => {
console.log("PUBLIC")
return (
<div>
<Header />
<Switch>
<Route exact path='/products' render={(props) => <Products />} />
<Route exact path='/profile' render={(props) => <UserProfile />} />
<Route exact path='/mycart' render={(props) => <MyCart />} />
<Route exact path='/' render={(props) => <Home />} />
</Switch>
</div>
)
}
export default PublicContainer
I have following route in BrowserRouter and Switch
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
<Router>
<Switch>
<Route exact path="/" component={HomeScreen}/>
<Route exact path="/about" component={AboutScreen}/>
<Route exact path="/products" component={ProductScreen}/>
<Route path="/product/:id" component={SingleProductScreen}/>
</Router>
</Switch>
All links are working perfectly in localhost. Except on the last route, nothing renders (not even 404 page) when I npm run build and then deploy.
I'm using react-router-dom for routing
Edit: This is what I get on my domain.com/product/1
This is my SingleProductScreen.js:
import React, { useEffect, useState } from 'react'
const SingleProductScreen = ({ match }) => {
const id = match.params.id;
return (
<div className="App">
<h1 className="title">{`Product Number: ${id}`}</h1>
</div>
)
}
export default SingleProductScreen
Once you build in react it will generate all static file.
For Dynamic routing it is more like
const App = () => (
<BrowserRouter>
{/* here's a div */}
<div>
{/* here's a Route */}
<Route path="/products" component={ProductScreen}/>
</div>
</BrowserRouter>
)
// when the url matches `/:id` this component renders
const ProductScreen= ({ match }) => (
// here's a nested div
<div>
{/* here's a nested Route,
match.url helps us make a relative path */}
<Route
path={match.url + '/:id'}
component={SingleProductScreen}
/>
</div>
)
I testing my React App and I have an error of all Link react router dom in my views.
Index.js
import {
BrowserRouter as Router,
Switch,
Route
} from "react-router-dom";
function App({props}) {
return (
<div>
<Navbar />
<Switch>
<Route path="/" exact component={Homepage} appProps={props}/>
<Route path="/accueil" exact component={Homepage} appProps={props}/>
<Route component={Error} />
</Switch>
<Footer />
</div>
);
}
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById("fatboar")
);
Homepage.js
import { Link } from 'react-router-dom';
export default function Homepage(props) {
return (
<Link to="/ajouter-ticket" className="primary-btn mt-5">Je participe</Link>
)
}
How my Link is outside of my router ?
The Link is navigate to /ajouter-ticket and as I see from your code you never put a Route to this Link due to this you navigate to the Error Component
and if you read the react-router-dom doc
you will see that when you navigate to something that doesn't define in the Switch Route go to the Route Without a path
React Router Dom Doc
<Route path="/ajouter-ticket" exact component={SomeComponent} appProps={props}/>
also, why do you have to routes to the HomePage?
Hello in my directions file I set my struct
header
navbar
and my switch
foote
const AppRouter = () => (
<BrowserRouter>
<Route path="/login" component={AuthPage} exact={true} />
<Route path="/dashboard/addProduct" component={AddProduct} exact={true} />
<div>
<Header/>
<Navigation/>
<Container maxWidth="lg" >
<Switch>
<Route path="/" component={LandingPage} exact={true} />
<Route path="/xd" component={AuthPage} exact={true} />
<Route component={NotFoundPage} />
</Switch>
</Container>
</div>
</BrowserRouter>
);
But I have two routes where I didn't want to show my header
footer
and nav bar
which are the login and addproduct routes
how could i do that?
This is a little bit hacky (just to match your current approach) since I'm assuming you just want to hide those components in only those 2 routes, You can use withRouter in your Header and Navigation components, withRouter will provide to you the location prop and you can have a condition like this:
import React from "react";
import { withRouter } from "react-router-dom";
const Navigation = props => {
const { location } = props;
const { pathname } = location;
if (pathname !== "/login" || pathname !== "/dashboard/addProduct" ) {
return (
// Component logic goes here
);
}
// if we're on those routes we should return null to not render anything
return null;
};
export default withRouter(Navigation);
If you want a more robust long term approach this answer could help:
How to hide navbar in login page in react router