React Router on pages with URLs that are not known in advance - reactjs

I have a massive preexisting website into which some new pages are going to be added that are being built on (client-side) ReactJS. The routes at which the new ReactJS pages will live are deep in the site: The ReactJS pages have to play nice with the existing URL structure, and that means that in a lot of cases, they won't know what their base URL is until they're deployed to production. (In some cases, they still won't know, because the upper parts of the URLs, the parts before the ReactJS page, are parameterized and will be changing on the fly.)
However, React Router seems to like absolute paths, and doesn't seem to play well with partial/relative/unknown paths. I've solved this by querying document.location.pathname upfront when everything loads — but it feels clunky, like React Router should be able to handle these kinds of relative paths out-of-the-box.
So here's my code, which does work:
const baseRoute = document.location.pathname;
...
render() {
return <Router>
<Route path={baseRoute} component={App}>
<IndexRoute component={HomePage}/>
<Route path={baseRoute + "/sub-page1"} component={SubPage1}/>
<Route path={baseRoute + "/sub-page2"} component={SubPage2}/>
<Route path={baseRoute + "/*"} component={NotFoundPage}/>
</Route>
</Router>;
}
...
render() {
return <div>
<IndexLink to={baseRoute}>Home</IndexLink>
| <Link to={baseRoute + "/sub-page1"}>Sub-Page 1</IndexLink>
| <Link to={baseRoute + "/sub-page2"}>Sub-Page 2</IndexLink>
</div>;
}
But this seems like a very clunky, brute-force way to handle it. It means that anything that needs a path needs to have access to that baseRoute variable, which is computed once at startup. It means that everything that uses routing needs to remember to use the baseRoute variable as well. And, to make matters worse, the code can't really be as simple as what I have above, since the incoming URL could contain a child route that only React Router knows about, so in some cases, string massaging is needed to properly compute the baseRoute.
It looks like they may have solved this issue more generally in React Router 4 by adding a basename property, but we're on React Router 3 right now.
So is there a better solution in React Router 3 to the app being hosted at an unknown URL, or are we stuck with passing around a derived baseRoute property?

Related

Nested React Router won't render

I have a popup component overlaying the main content that I want to render through routing, but because I want it to build on existing routes without messing up my main page configuration, I have tried going for a nested route. However, I seem to have misunderstood how it is supposed to be done. I wrapped the export with "withRouter" and tried to do this:
<Fragment>
<Helmet>
<title>Videos - Saddex Productions</title>
</Helmet>
<Switch>
<Route path="/popup"
render={() => <Popup items={props.videos}/>}
/>
</Switch>
...
This doesn't work and only renders the main component. And I also don't want to outsource the code that's going to be rendered underneath, because it seems unneccessary. However, what should I do? Thanks in advance.
Solved: The reason it didn't work is because I presumed the router works like the Express router does - with relative paths. I included the base path like "videos/popup" and now it works, it seems.

how to use react-router for dynamic url

I am building extremely stretchable react app and I am using SSR fro SEO.
but I don't know how to handle URL
Like: user can directly land on this URL, domian.com/delhi/cardiologist
In the backend, I have a system of identifying the components for URL, which is for this case is "Speciality" component in "Location: component
I can't go like this
<Rout path={"delhi"}>
<Location/>
</Route>
cause for this case it's Delhi. but for another user, it will be a different city name, I want to reflect the different city in URL but to render same component due best SEO.
SEO is heart of my app.
I am literally new to this kind of things.
please guide me.
I would recommend adding some structure to the path that makes it easier for you to find the location, say:
<Route path='/search/:city/:specialty' component={Specialty} />
So this would match domian.com/search/delhi/cardiologist. You can customize it to whatever makes sense, it could even be a short letter like just /go/ if you are concerned about URL length because of SEO.
Then, inside the Specialty component, you can use match.params.city and match.params.specialty to get the parameters that you are looking for:
function Specialty({ match }) {
const { city, specialty } = match.params;
return (
<p>Search for {specialty} in the city of {city}</p>
);
}
You could still implement a catch-all route using the path that you want:
<Route path='/:city/:specialty' component={Specialty} />
However, that would require always setting the route at the end, so that it only lands on your <Specialty /> component if it doesn't match any other path that you have.

What exactly is Dynamic Routing in ReactJS

I have been all around internet about the dynamic routing of React. But I couldn't find anything which explains how it works and how it is different than static routing in every single sense.
I understood it pretty well how the things go when we want to render something in the same page using React-Route.
My question is how does it work when a whole new page is wanted to be rendered? Because in this case all the DOM inside that page has to be re-rendered. Thus would it be static routing? or still dynamic in some ways?
I hope I've been clear.
Thanks for the answers in advance, I appreciate!
I don't think the above explanation is correct for Static vs Dynamic routing.Also there is not much explanation in the web for it, but there is a very nice explanation in React Router Docs.From the Docs
If you’ve used Rails, Express, Ember, Angular etc. you’ve used static
routing. In these frameworks, you declare your routes as part of your
app’s initialization before any rendering takes place. React Router
pre-v4 was also static (mostly). Let’s take a look at how to configure
routes in express:
In Static routing, the routes are declared and it imported in the Top level before rendering.
Whereas in Dynamic routing
When we say dynamic routing, we mean routing that takes place as your
app is rendering, not in a configuration or convention outside of a
running app.
So in Dynamic routing, the routing takes place as the App is rendering.
The examples explained in the above answer are both for static routing.
For Dynamic routing it is more like
const App = () => (
<BrowserRouter>
{/* here's a div */}
<div>
{/* here's a Route */}
<Route path="/tacos" component={Tacos}/>
</div>
</BrowserRouter>
)
// when the url matches `/tacos` this component renders
const Tacos = ({ match }) => (
// here's a nested div
<div>
{/* here's a nested Route,
match.url helps us make a relative path */}
<Route
path={match.url + '/carnitas'}
component={Carnitas}
/>
</div>
)
First in App component only one route is declared /tacos.When the user navigates to /tacos the Tacos component is mounted and there the next route is defined /carnitas.So when the user navigates to /tacos/carnitas, the Carnitas component is mounted and so on.
So here the routes are initialized dynamically.
Use react-router and react-router-dom, and write something like this:
onSubmit((e) => {
e.preventDefault();
this.props.history.push('<url>')
}
so at any place you may run this line and go to another locations conditionaly

Using multiple params with React Router?

<Route path="/:user" component={Home}>
<Route path="/:thing(/:version)" component={Thing}/>
</Route>
So, I've got two dynamic objects in my application that I'd like to be controlled by route params in react-router. Using the code above, both /0 and /0/3 take me to Home. I need /0/3 to take me to Thing. I'm not sure what I'm doing wrong here... Does react-router even support multiple dynamic params next to each other like this? I couldn't find anything in the docs.
What happens here is that you've given React Router two paths that can both match on /anything. By default then React Router matches the first one it can find.
To dig deeper, if I go to /pudding, React Router can't know if you meant /:user or /:thing. Since /:user occurs first, that option will be chosen.
You also need to make sure if nesting routes is what you want. Currently, your Thing route is nested below Home, which means that it is rendered via this.props.children in your Home component. So, for your current Thing route, Home will always be rendered too, with Thing as a child. If your Home component doesn't render this.props.children, Thing will not be shown.
I suspect you just want two different pages. What you could do to achieve that is the following:
<Router history={history}>
<Route path="/user/:user" component={Home} />
<Route path="/:thing(/:version)" component={Thing}/>
</Router>
This will make every /user/name go to the Home component, and every other /random (with an optional extra level) will go to Thing. If you wonder why in this case React Router doesn't take /user/name to the Thing route, it's because it still matches in the order your routes are specified. Because your Home route matches the requested URL, no siblings of this route are tested anymore.

React-router child-route navigation not working

I'm trying to follow the react-router tutorial here trying to navigate using a child route and it doesn't work.
For example given this route definition:
export default <Route path="wifi" component={ Wifi }>
<IndexRoute component={WifiView}/>
<Route path="list" component= {WifiListView}/>
<Route path="connect" component={WifiConnectView}/>
</Route>;
If we are on "/" and navigate to "/wifi" we are good. The WifiView is presented however if if from "/wifi" we call hasHistory.push('list') it doesn't find the route. I would assume that the route is relative to its current location since I'm not using the "/" but that isn't being respected.
Also the document said:
You can also use the router that Router provides on "context". First,
you ask for context in the component, and then you can use it...
But I don't see anything that mentions how to do that in TypeScript so I'm using the static hashHistory.
It looks like novice questions but I had nowhere to ask since the suggested Discord channels are all dead... Can anyone help with those?
Thanks! Appreciate any help!
Ok finally found the replies to my questions...
As for today, react-router don't support relative navigation which means, it hast to navigate to the whole chain of routes and that is why hasHistory.push('list') doesn't work.
In order to get the context.router we need to use withRouter high order component but that isn't exposed on the TypeScript definition files they provide.

Resources