can we reload the same component with different urls? - reactjs

I have my component "messages" and i am calling it using two different urls .when i click on first link say 'messages/1' it will load my messages inbox and i have another url 'messages/5/1' for which the component is same as for above url.when page got loaded using 'messages/1' url and when i clicked on some field which points to 'messages/5/1' .It changes the url in the header but it is not reloading the page.
i want to reload my component whenever there is different url even though they have same component .Is there any way to do this.

You can load the same component under different urls and it should load everything fine. Just change the path prop and add the same component you want under the component prop.
render((
<Router>
<Route path="/" component={App}>
<Route path="about" component={About} />
<Route path="inbox" component={Message}>
<Route path="messages/:id" component={Message} />
</Route>
</Route>
</Router>
), document.body)
edit:
You can try and use rect-router's refresh method
from https://github.com/reactjs/react-router/blob/v0.13.3/modules/createRouter.js#L435-L437
refresh: function () {
Router.dispatch(location.getCurrentPath(), null);
},

Related

to intercept a route change in react

We have a web service through which you can block a specific route, whenever user hits that particular route - what I want is if the web service has block it then that route should not get displayed.
Is it possible in react, react-router?
You can do something like this,
<Switch>
<Route exact path={"/protected-path"} component={canAccess ? View : NoView} />
<Route path="/404" component={NotFound} />
<Redirect to="/404" />
</Switch>
NoView and View are react components. canAccess is a boolean value that checks user has access to that content.

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).

How to tell google bot that page not found in React?

I have a React App with Routers, I also have 404 component, etc.
But I don't know how to send 404 header to google bot.
I'mm just thinking that it's not possible due React app without SSR.
Am I right?
If you are using Router, you can set your pages like this:
<Router>
<Switch>
<Route exact path = "/home" component={HomePage} />
<Route exact path = "/sign-up" component={SignUpPage} />
<Route exact path = "/login" component={LoginPage} />
<Route exact path="/incorrect-login" component={IncorrectLoginPage} />
<Route exact path = "*" component={PageNotFound} /> //404 Component
</Switch>
</Router>
With this, you set your PageNotFound to the bottom of your router list where if the url of the React App does not correspond to any of your previous urls, then the PageNotFound route is triggered. You can just render your not found component under that page like you would for any other page in your application.
I also used exact so that the url must be exactly the same along with a Switch statement so that only a SINGLE page component can be triggered at once. The * basically just means ALL other urls besides those specified previously.
The PageNotFound is treated as kind of like a default catch statement so it's at the bottom

React router dom params issue

I tried to Routing the params ":id" in react with a sub Route ":id/history" and the route link not render the component on clicking
<Switch>
<Route path="/patients/:id" exact component={GeneralData} />
<Route path="/patients/:id/history" component={History} />
</Switch>
The Switch component renders the first route that matches the URL you entered
Because you are using a wildcard for your GeneralData Route like so
<Route path="/patients/:id" component={GeneralData}/>
No matter what you enter after /patients, it gets captured in that wildcard definition of that Route because it accepts literally anything. So even if you navigate to /patients/4834834/history it still satisfies the GeneralData route which was found first in the list of routes.
To fix this, simply move your History Route above your GeneralData Route. This makes it so the GeneralData route will not get rendered for anything that just satisfies /patients/:id. Switch will look to see if your URL matches History first.
<Switch>
<Route path="/patients/:id/history" component={History} />
<Route path="/patients/:id" component={GeneralData} />
</Switch>
I think you're omitting exact param.

Nested router not rendering components correctly

I'm having a weird bug with nested routes in react-router that I'm struggling to fix.
I have two components where I have multiple routes in them. One is a settings component and the other is a profile component. In my settings component things work perfectly fine.
I have three files in my component folder (index.js, editprofile.js, and password.js). I import the components in my index file. Then render them like this.
index.js // settings component
...html that renders across all routes
<Route path="/account/settings" exact component={EditProfile} />
<Route path="/account/settings/password" component={Password} />
This works as planned. On /account/settings the edit profile component renders and when I link to /account/settings/password the password component appears and the edit profile component is gone.
Now the bug I have is when I try to do the same exact thing in my profile component. I have similar file structure in my profile component (index.js, timeline.js, followers.js, following.js...). I import them into my index.js and render them in the component like this.
index.js // profile component
...html that renders across all routes
<Route path="/:username" exact component={Timeline} />
<Route path="/:username/followers" component={Followers} />
...other <Route />'s
This loads the Timeline component correctly but when I link to any other routes it loads a blank page. As an alternative I tried to edit the path like below:
<Route path={{pathname: '/' + this.props.user.Username}} exact component={Timeline} />
<Route path={{pathname: '/' + this.props.user.Username + '/followers'}} component={Followers} />
And this resulted in the followers component being rendered on what should be /:username and the blank page rendering on /:username/followers.
Any idea's as to why this process doesn't work with my profile component but works fine with settings component?
Edit** A third alternative I tried was to put the match.params into the pathname. Eg.
<Route path={{ pathname: this.props.match.params.username }} component={Timeline} />
<Route path={{ pathname: this.props.match.params.username + '/followers' }} component={Followers} />
This gave me a similar result as one prior.
The problem is the <Route path="/:username" exact component={Timeline} /> will match more routes than you assume.
E.g., it'll match:
/about // username = about
/followers // username = followers
and so on. You'd need to make it more specific or declare it as the last route.

Resources