React-router child-route navigation not working - reactjs

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.

Related

Is it possible to hide secret URL paths when using React Router?

I'm new to React, and have a n00b question and Googling hasn't turned up any good answers, maybe someone here knows:
With React Router or any kind of declarative routing, how do you "hide" private URLs that you don't want every user to know about? Or, if you just want to prevent someone from being able to easily enumerate all valid URLs?
Code splitting doesn't solve this (really) because the user is told what to request to get the rest of the information: I suppose you could put that URL behind authentication or some kind of restriction to prevent public access to it, but won't that cause the JS fetching the code-split import to receive an error, causing that error to bubble up and cause unintended failure behavior?
Edited to add:
The crux of my issue is wanting to essentially do <Route path="/:path"> where :path matches the entire URL path (e.g., could be foo/bar/baz) instead of just the first "part" (e.g., foo) for a URL like https://example.com/foo/bar/baz for example.
I could use <Route path="*"> and do my own URL parsing, but what if I don't want that route to actually handle the request? How do I signal "nope, I don't want this request, fall-through to the next matching Route"?
You can check if the user is authorized to see these routes and then show or hide them.
<Route path="/cities" component={City} />
<Route path="/courses" component={Courses} />
{user.hasPermission && (
<Route path="/secret" component={VerySecretPage} />
)}
If you want to go further, you can create a custom guarded route as described in this blog post.

How do I make a url contain multiple sections? React

So full disclosure, I'm not sure how to ask this question properly, but I do have a decent example. I'm making a React app and I'm trying to make the url more "descriptive" I suppose.
So it starts off at Home, then I go to a Products page and the url changes from /home to /products. This part is fine.
When I want to go to a specific product from the product page, I want the url to change to /products/example instead of just /example. Do I have to specify this with the Links or is there some cleaner way to get it done?
Right now my only answer is to make the link go to /product/example and have the App.js route to the same url. I'm not sure how to properly ask this question for a Google search so I had to ask it here. If you have an idea how to specifically phrase what I'm asking, I'd appreciate that too.
Thanks in advance.
I believe the example in your URL /products/example is the product name for your product. If so, this can be done in putting the product name as an URL parameter using react-router or react-router-dom if you still have not.
by declaring the route as
import { Switch, Route } from "react-router-dom";
const Router = () => (
<Switch>
<Route exact path="/home" component={()=>return <h1>Home</h1>} />
<Route exact path="/products" component={()=>return <h1>Products</h1>} />
<Route path="/products/:productName" component={props=>return <h1>props.match.params.productName</h1>} />
</Switch>
);
export default Router;
more on that here

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.

Does importing a component for use with React-Router display the stylesheets used in that component, even when that component is not being rendered?

While using react-router for a multi-page react app, I've found that the different components that are to be rendered based on the path display the stylesheets in those components, even when the corresponding component isn't displayed.
I was playing around with adding a Sponsors page to my website, and the CSS was behaving strangely. Digging deeper into the problem with chrome devtools, I found that the css from my homepage was on the page while it was not being displayed, causing unexpected styles.
I've tried researching if this is the expected behaviour without any luck. I removed the homepage from my routing code and the styles behaved as expected in the other component, proving that that import was the problem.
My routing code:
<Switch>
<Route
exact path="/"
render={props => <MainPage language = {this.state.language}/>}
/>
<Route
path="/Sponsors/"
render={props => <Sponsors language = {this.state.language}/>}
/>
</Switch>
Of course with
import Sponsors from './Pages/Sponsors/Sponsors.js'
import MainPage from './Pages/MainPage/MainPage.js';
at the top of that file.
and at the top of MainPage.js:
import './MainPage.css';
An import that looks like that, and the same type in Sponsors.css.
Any code in that MainPage.css will affect the elements in the Sponsors component, even when the url is at /Sponsors (i.e. the MainPage component shouldn't be rendering).
I'm looking to ensure I understand the behaviour of react-router, that the MainPage.css should not appear when MainPage is not being rendered. As an alternative I could write specific enough css that this never happens, but It was my understanding that the modular nature of react featured that not being a necessity, as in I can write it only specific enough for the code being rendered. Am I mistaken?
I understood you are trying to limit the scope of CSS to a module, generally it is having a global scope. you can use "CSS Modules", to overcome this behaviour.
please find the article from facebook.
https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet
hope it will help to fix the issue.

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.

Resources