React Router and Links all directing to the same page? - reactjs

Im pulling my hair out trying to figure out why the list of react Links is all just loading the error page. Could anyone advise please? its almost a direct copy of a previous project that worked perfectly.
Router Set up
function App() {
return (
<Router>
<Switch>
<Route exact path = '/'>
<Home />
</Route>
<Route path = "*">
<Error />
</Route>
<Route path = '/about'>
<About />
</Route>
<Route path = '/contact'>
<Contact />
</Route>
<Route path = '/deckbuilder'>
<DeckBuilder />
</Route>
</Switch>
</Router>
)
}
export default App;
Links on Home Page
export const Home = () => {
return (
<div>
<h1> Home Page </h1>
<Link to = '/contact'>
Contact
</Link>
<Link to = '/about'>
about
</Link>
<Link to = '*'>
Error
</Link>
<Link to = '/deckbuilder'>
Deck
</Link>
</div>
)
}

You should use react router like this and put error component at last, this is correct syntax:
<Switch>
<Route exact path='/' component={Landing} />
<Route exact path='/sign' component={Sign} />
<Route exact path='/login' component={Dashboard} />
<Route component={GenericNotFound} />
</Switch>

I'll add some more information to the #Shivam Jha answer.
worked, strange as this didnt happen on my last project at all
There's no way to work this on previous project if your router configuration is same like above. This issue in not specific to the React router. Even when developing backend applications this can happen.
The thing which make the problem is that start(*) mark. This mark represent any value. By that mean, the second router declartion of your code, i.e route for <Error /> triggered every time when the url is match to *.
That mean,
/abcd
/sign
/login
All of the above paths match to *. So React router does not even check the next router declarations. It simply route to the <Error /> page. So as the solution, you should always declare static routes at the top of the configuration while things like *, :id defined at bottom
Another case is, If you have, two routes as
abcd.com/posts
abcd.com/:id
then If you defined the abcd.com/:id above the abcd.com/poststhen you will never able to send a request to the /posts endpoint. This is not only specific to React router. Even when doing backend development, you have to be aware of this.

Related

React Router change the link but can't changed the body

React router Link tag wokred in the first page and page also changed but in the 2nd page have many link If i click on this link it can changed the link but not body how can i fix it...
Router code :
<Switch>
<Route exact strict path="/">
<Home />
</Route>
<Route exact strict path="/about/">
<About />
</Route>
<Route exact strict path="/channel/:title" component={withRouter(Dashboard)} />
</Switch>
</div>
</Router>
2nd page code
function Dashboard() {
const { title } = useParams();
return (
<div>
<Play
title={title}
/>
</div>
);
}
Passing some data via props
//this is <Play/> component code just showing here shortly
<Router>
<VideoPlayer
controls={true}
src={this.state.link}
poster={this.state.poster}
width={window.screen.width}
height={window.screen.height - (window.screen.width+100)}
/>
<Link to="/channel/Rtv">Rtv</Link>
</div>
</Router>
just showing a little part of this code...
please help me ...how can i fix the error
Full code is here:
https://gist.github.com/fahadali32/8643d33a2328c1375552e4ba7637fc92
withRouter's documentation mentions:
withRouter does not subscribe to location changes like React Redux’s connect does for state changes. Instead, re-renders after location changes propagate out from the <Router> component. This means that withRouter does not re-render on route transitions unless its parent component re-renders.
This is not the behavior you want, so you shouldn't use withRouter.
So you should replace the line
<Route exact strict path="/channel/:title" component={withRouter(Dashboard)} />
with
<Route exact strict path="/channel/:title" component={Dashboard} />
If you need to access match or location or history, use the corresponding hook. You're already using useParams; you could also use useLocation or useHistory if you need them.
Ok i find the answer just simply add
<div key={this.props.link}>
<VideoPlayer controls={true} src={this.state.link} poster={this.state.poster} width={window.screen.width} height={window.screen.height - (window.screen.width+100)} />
</div>

React router does not render route when URL accessed directly

Consider this the main App component (imports left out for brevity):
const App = () => {
const [orderRoutes, setOrderRoutes] = useState([])
const updateOrderRoutes = (newRoute) => {
orderRoutes.push(newRoute)
setOrderRoutes(orderRoutes)
}
const renderedOrderRoutes = orderRoutes.map(route => {
return (
<Route
path={`/${route.class}/${route.order}`}
exact
key={`/${route.class}/${route.order}`}
>
<CatalogPage />
</Route>
)
})
return (
<BrowserRouter>
<Header
updateOrderRoutes={updateOrderRoutes}
/>
<Route path="/" exact component={Home} />
<Route path="/aboutus" exact component={AboutUs} />
<Route path="/faq" exact component={Faq} />
<Route path="/register" exact component={Register} />
{renderedOrderRoutes}
<Footer />
</BrowserRouter>
)
}
export default App
The challenge is that some of the routes are not known when rendering the initial App component. They will be known when an AJAX request in the <Header> component is responded to. The header will then update the new route to the orderRoutes state property, re-rendering the App component every time. The routes that are the result of the AJAX call (that is made in the <Header>) are then rendered to the <BrowserRouter> (in {renderedOrderRoutes}). In the <Header>, there is a <Link> for each route being rendered as a result of the same AJAX call, so that every menu entry (The <Link>s) will have a corresponding route.
This works fine, but when I access one of the URL's that this mechanism generates directly (e.g.: refresh the page), the <CatalogPage> component is not rendered.
So, for instance let's say that the AJAX call results in a bunch of routes and one of those is /t-shirts/tanktops. I will get a menu entry with a link to that path. When I click that menu entry the <CatalogPage> component is rendered. But when I access /t-shirts/tanktops directly, the <CatalogPage> component is not rendered.
How can I alter this code to make the URL's that are a result of the AJAX call directly accessible?
EDIT
OK, I 'solved' this (don't like it) by forcing the <App> component to re-render when one of the <Link>s was clicked by creating an unused piece of state on the App component called activeOrderRoute. I passed the setter down to the Header as a prop and connected it as a callback to the onClick handler for each Link that was created in response to the AJAX request. This essentially forces the App to re-render and render the routes, which solved my problems.
Still, that does not seem like the correct way to do it so any help would be appreciated.
React router does not directly have routing support for all URLs. It catches the default domain only the remaining routing is done on client side and requests are not served.
If your domain is www.mydomain.com, you can not access the URL www.mydomain.com/info directly in the react router.
Solutions:
You can use a hash router but that makes the URLs unfriendly for SEO
You can set up a catch-all routes and route it yourself
This link would help you with the same
https://ui.dev/react-router-cannot-get-url-refresh/
you need to modify your webpack.config.js and add the following lines.
module.exports = {
devServer: {
historyApiFallback: true,
},
...
Instead of trying to explicitly render a route for each asynchronously fetched route, leverage the power of react-router-dom and render a dynamic route path string that can handle any catalog page.
Instead of this:
const renderedOrderRoutes = orderRoutes.map(route => {
return (
<Route
path={`/${route.class}/${route.order}`}
exact
key={`/${route.class}/${route.order}`}
>
<CatalogPage />
</Route>
)
})
return (
<BrowserRouter>
<Header
updateOrderRoutes={updateOrderRoutes}
/>
<Route path="/" exact component={Home} />
<Route path="/aboutus" exact component={AboutUs} />
<Route path="/faq" exact component={Faq} />
<Route path="/register" exact component={Register} />
{renderedOrderRoutes}
<Footer />
</BrowserRouter>
)
Render a single dynamic route in your Router. Use a Switch so only a single route component is matched and rendered. Reorder the routes so the more specific paths can be matched before less specific paths. Now, when a URL has a path that is of the shape "/someClass/someOrder" it can be matched before you try matching any of the more general paths. You will see that the home path ("/") is matched last and the reordering allows us to remove the exact prop on all routes.
return (
<BrowserRouter>
<Header updateOrderRoutes={updateOrderRoutes} />
<Switch>
<Route
path="/:class/:order"
exact
component={CatalogPage}
/>
<Route path="/aboutus" component={AboutUs} />
<Route path="/faq" component={Faq} />
<Route path="/register" component={Register} />
<Route path="/" component={Home} />
</Switch>
<Footer />
</BrowserRouter>
)
You may need to adjust some logic in CatalogPage to handle possible undefined catalog data, whatever it is using from the route props/etc... to render catalog stuff.
In your Header component make the asynchronous call there to fetch the routes that can be navigated to so you can dynamically render render links to them (if that is even why you are passing the routes to Header).

Having issue with defining path for image in a react application

I'm having an issue with defining image path in react application and it's getting frustrating so I'm seeking help from the pros. I'm moving my images folder back and forth between public and src. When background:url(path) works, img src="path" doesn't work and vice-versa. I get this error "Error: Can't resolve 'images/img-2.jpg' in '/Applications/MAMP/htdocs/react-web/src'". If I move the images folder to src, it works but the background:url(path) does not load image. I have the project in https://github.com/miraj977/react-project/. Another issue is github pages; I have setup this project in gh-pages (https://miraj977.github.io/react-project/) but it only loads up to nav and stops. Doesn't load body. Also, I have set homepage in package.json "https://miraj977.github.io/react-project/" but whenever I click the logo which should redirect to homepage, it redirects to "https://miraj977.github.io/". I have shared the link to the github project for you to review the code. It's getting quite frustrating now. Please guide me on the right way to solve these issues. Your time is highly appreciated. Thank you in advance.
Only the navbar showing is actually related to your routing configuration.
Instead of this:
function App() {
return (
<>
<Router>
<Navbar />
<Switch>
<Route path="/" exact component={Home} />
<Route path="/services" exact component={Services} />
<Route path="/products" exact component={Products} />
<Route path="/sign-up" exact component={SignUp} />
</Switch>
</Router>
</>
);
}
do this:
function App() {
return (
<>
<Router>
<Navbar />
<Switch>
<Route path="/react-project" exact component={Home} />
<Route path="/react-project/services" exact component={Services} />
<Route path="/react-project/products" exact component={Products} />
<Route path="/react-project/sign-up" exact component={SignUp} />
</Switch>
</Router>
</>
);
}
Since your homepage url is suffixed with /react-project you want to account for this in your routes and redirects.
So to be extra clear your navigation Link components in your Navbar should also be changed from this:
<Link to="/" className="navbar-logo" onClick={closeMobileMenu}>
1 TRVL 2 <i class="fab fa-typo3" />3{" "}
</Link>
to this:
<Link to="/react-project" className="navbar-logo" onClick={closeMobileMenu}>
1 TRVL 2 <i class="fab fa-typo3" />3{" "}
</Link>
As for the image problem.
For specifying the img by src you can do something like this:
import img1 from "../images/img-1.jpg"; // relative path from directory this component file is in
// ...
<CardItem
src={img1}
text="Explore the hidden waterfall deep inside the Amazon Jungle"
label="Adventure"
path="/services"
/>
For specifying an image as a background image via css you can do something like this:
background: url("../images/img-home.jpg"); // Also relative to current file location
Paths from the public url apparently don't resolve like they used to anymore in create react app 4, see this github issue.

Why react router redirects from the parameter route to '/'?

I have the following router structure:
<Router>
<Switch>
<Route exact path={'/books'}>
<p>All books</p>
</Route>
<Route path={'/books/:bookId'}>
<p>book with ID</p>
</Route>
</Switch>
</Router>
Whenever I navigate to /books/:bookID, after a split second there, I got redirected back to /books. No Redirects present, but I got pushed back to /books with putting url manually, or using history.push().
<Link /> can't be used, but it didn't help as well.
<Button onClick={() => history.push('/books/5')}>Go to book 5</Button>
Would be glad to any hint on this matter.

React route does not detect nesting routing and ids

I have some React routes that when I nest one route inside another, I need to repeat the route path.
To explain, for example:
<Route
path="admin">
<Switch>
<Route
path="admin/specific/:id"
component={SpecificAdmin} />
<Route
exact
path="admin"
component={AdminPage}>
</Route>
<Route
exact
path="admin/edit/new"
component={EditSpecificAdmin} />
</Switch>
</Route>
I want a page where I can see the list of items, one for adding a new one and another for looking, editing a specific item. So I thought about the paths edit/new and specific/1.
So the routes do not detect when I write specific/1 (the specific id) and not either the admin nesting, so I need to write the admin in each one...
As Tareq aziz said, you can easily have intel in props.
You can create another router to pass easily new value:
// your original component
import AdminRouter from './Admin/Router';
export default () => {
return (
<Route path="admin">
<AdminRouter />
</Route>
);
}
// in ./Admin/Router.js
export default (props) => {
return (
<Switch>
<Route
exact
path={`${props.match.path}/specific/:id`}
component={SpecificAdmin}
/>
<Route
exact
path={`${props.match.path}`}
component={AdminPage}
/>
<Route
exact
path={`${props.match.path}/edit/new`}
component={EditSpecificAdmin}
/>
</Switch>
);
}
I'm not sure though if the order of the routes are correct.
I think you can get your current page's url from props using location.pathname or match.url. You can see my image. Then you may add your nested route after that. Hope it will help you
You may code your path like this way
path=`${this.props.location.pathname}/edit/new`
path=`${this.props.location.pathname}/specific/:id`

Resources