I have two routes, a base path and a customer route. The customer route takes a customerId parameter.
<HashRouter>
<Switch>
<Route path="/mapper/:mappingId/" exact component={Mapper}/>
<Route path="/" exact component={App} />
</Switch>
</HashRouter>
then in the react component I am calling it like this to navigate
window.open(`/customer/${customerId}`)
(updated, still doesn't work)
but when I navigate it just goes to the App component. I have to use HashRouter because the react app is wrapped in Electron. BrowserRouter works on the web
The url i get when i navigate is this:
http://localhost:3000/customer/ca023754-bb75-4f64-a19c-958525b53e12#/
I also tried adding backslash in Route, /customer/:customerId/, that didn't work as well
I have read How to use React Router with Electron? but it doesn't really work
I finally figured this out. Hashrouter expect the url to have "#/" after the basepath. so it should be window.open('#/customer/${customerId}')
Related
I want to be able to serve a React app using React Router both on an Apache and NGINX server without having to change any default Apache/NGINX configs.
The problem is that the application will only be served when you access the root folder, as any sub path leads to a 404 (app.com/ works but not app.com/settings).
For the Apache server, I include a .htaccess file that automatically loads index.html if the requested resource is not found.
For NGINX as far as I understand there is no way to properly load the application in a sub-path unless you change the config file.
My solution for this would be to add the option in the app to store the Router path as a query string, instead of in location.pathname, something like app.com/?page=settings instead of app.com/settings.
Is there any way to add some sort of a middleware in the React router such that when accessing app.com/?page=settings the Router path will be set to /settings. Also, when the user navigates and the router should update the URL in the address bar, it should change it to app.com/?page=user/dashboard instead of app.com/user/dashboard.
I am looking for any solution that would allow the Router to work both with a path and with the path specified as a query string variable.
If needed, here is how my router looks:
<Router history={browserHistory}>
<Route path={BaseRoutes.Home} exact>
<Redirect to={BaseRoutes.Domains} />
</Route>
<Route path={[BaseRoutes.Stats, BaseRoutes.Settings, '/*']} component={SidebarMain} />
<div className={`content-area ${classes.content}`}>
<Switch>
<Route exact path={BaseRoutes.Stats} component={Stats} />
<Route exact path={BaseRoutes.Home} component={Domains} />
<Route exact path={BaseRoutes.Settings} component={Settings} />
</Switch>
</div>
</Router>;
Never mind, I realized I can just use HashRouter instead of Router for NGINX...
So, depending on whether the user's setting of having "pretty" URLs or hash based URLs I can either load the BrowserHistory Router or the HashRouter:
<Router history={browserHistory}> OR <HashRouter>
To switch between them I did:
let SupportedRouter: React.ElementType = HashRouter;
if (MY_CONDITION) {
SupportedRouter = Router;
}
// Render
<SupportedRouter history={browserHistory}>
</SupportedRouter>
I had to cast them to React.ElementType, otherwise optionally passing history lead to TypeScript errors: https://github.com/microsoft/TypeScript/issues/28631#issuecomment-472606019
I've used React Router like below:
<BrowserRouter>
<Switch>
<Route exact path="/" component={Login} />
<Route exact path="/home" component={HomeComponent}/>
</Switch>
</BrowserRouter>
When I use this.props.history.push("/home") or http://localhost:3000/home page is Moving to Home page, but the url is still http://localhost:3000/.
Routing is working and I am able to navigate to all pages, but in the Top URL bar it is showing http://localhost:3000/ always.
Any Idea why this happens?
Please check whether u have implemented any createBrowserHistory, if its there please remove it (assuming it's an implementation issue).
Try adding the BrowserRouter to your index.js instead of adding in the inner component.
ReactDOM.render(<BrowserRouter><App /></BrowserRouter>, document.querySelector('#root'));
I'm having a strange issue with React Router. My PrivateRoute wrapper doesn't do its thing when navigating using a Link or NavLink.
Essentially I have something like this:
<BrowserRouter>
<Switch>
<Route exact path="/"><Home /></Route>
<PrivateRoute exact path="/private"><Private /></PrivateRoute>
</Switch>
</BrowserRouter>
PrivateRoute is just a wrapper around Route that checks for authentication.
Now, if I go to /private by typing it in the address bar, PrivateRoute does its job (and redirects to /login, but that doesn't matter).
However, if I use a NavLink in the Home component which has to="/private", React Router routes to the private route even if the user is unauthenticated.
Is there any way I can resolve this reasonably? And why does React Router behave like this and doesn't "go through" all the routes in BrowserRouter each time you navigate using a NavLink?
To solve your problem, you need to add exact or exact="true" on public Route.
If you don't include exact="true", <Route path="/"> refers all sub routes starting with /.
So /private will match / route hence it will render <Home /> component.
Here is updated code
<BrowserRouter>
<Switch>
<Route path="/" exact>
<Home />
</Route>
<PrivateRoute path="/private">
<Private />
</PrivateRoute>
</Switch>
</BrowserRouter>
Here is sample code
Well, this was a quite simple and dumb fix actually.
The problem was that the PrivateRoute component didn't "remount" when changing routes using Links (that is interesting and somehow clever behavior of React Router, I can imagine this improves performance).
Meanwhile, typing a URL into the address bar refreshes the entire page, thus "remounting" all components.
Since the logic for checking auth was in componentDidMount only, it didn't launch if the component wasn't "remounted", therefore creating my issue.
For any possible future visitors, to fix this problem, just move your auth checking logic from componentDidMount somewhere else, and reference it both in componentDidMount and componentDidUpdate. Don't forget to check if props actually changed in componentDidUpdate — otherwise you'll create an infinite loop — like so:
componentDidUpdate(prevProps, prevState) {
// You could also use shallowCompare, but that wasn't needed in my case
if (this.props.requiredPerms !== prevProps.requiredPerms) {
this.checkAuth(); // method with the logic which was in componentDidMount before
}
}
I'm transitioning a project from using HashRouter to BrowserRouter, however there are some links in other sites and email campaigns that are linking to the site using the old HashRouter URLs. Is there a way to redirect those to not use the /# in the url?
For example if linked to
#/planet/mars
It should redirect to
/planet/mars
I tried a Switch/Redirect shown below but that doesn't seem to be working.
<Switch>
<Redirect from="/#/planet/:planet" to="/planet/:planet" />
<Route
path="/planet/:planet"
exact
component={PlanetPage} />
</Switch>
I am experimenting with react in an Angular app. I am currently using ngReact to load react components in my angular app.
I am using react-router (2.8.1) for a section of my app. I created another section and want to use react-router as well. Unfortunately, I am running into problems, the only Router that works and is recognized is the first router I visit. Here is what I've observed.
Both Routers load when my app loads the homepage. How do I know? I added a property to the Router object and console.logged the properties in the files the routers are created.
If I visit Router A first, Router A works! When I visit the page using Router B, Router B doesn't seem to be recognized and doesn't work, I get the error "Warning: [react-router] Location "/RouteB" did not match any routes". This solution did not work.
Do I need to refactor my routers into a large file that includes all my Routes I use with react-router? It seems like I need to refactor everything or I am missing something.
I am more familiar with backend routing, specifically using express.Router where an instance is created and the router isn't shared.
Here are snippets of my two Routers that are used in different sections of my app.
Router A:
import React from 'react';
import {Router, Route, browserHistory, IndexRoute} from 'react-router';
/* Note, additional import statements for components */
const Routes = () => (
<Router history={browserHistory}>
<Route path="/RouteA">
<IndexRoute component={UserIndex} />
<Route path=":RouteAId">
<IndexRoute component={index} />
<Route path="user" component={user} />
<Route path="profile" component={profile} />
<Route path="preview" component={previewUpdate} />
<Route path="interest/:interestId/resume" component={CoverLetterRoute} />
</Route>
<Route path="*" component={NoMatch} />
</Route>
</Router>
);
export default Routes;
Router B:
import React from 'react';
import {Router, Route, browserHistory, IndexRoute} from 'react-router';
import Main from '../components/Main';
const Routes = () => (
<Router history={browserHistory}>
<Route path="/onboarding" component={Main} />
</Router>
);
export default Routes;
Is it possible to have two separate routers like this? Do I need to load all of my routes into one Router? Please comment if you need more information.
Use a single client-side app with a single router by using different routes. This would allow you to share code more easily, and seamlessly link from one part of the app to the other. You'd have to setup your server to serve the same script for both /users and /onboarding.
var routes = (
<Route handler={App}>
<Route path="/users/welcome" handler={Welcome} />
<Route path="/onboarding">
{/* onboarding routes here */}
</Route>
</Route>
);
2nd option (not recommended though): Use two different entry points each running its own router. This would isolate each of your apps, and you wouldn't be able to transition from one "app" to the other without a server round trip. You'd have to setup your webpack and server so that it serves different (entry) scripts for /users and /onboarding. And for linking to the other app, you'd have to use the normal <a href> instead of <Link to>.