React router get currently active segment as param - javascript

I have following router configuration
<Router history={history}>
<Route path="/" component={ReviewWizard}>
<IndexRoute component={Administrative}/>
<Route path="Administrative" component=Administrative}>
<Route path="/Administrative/:itemId" component={AdministrativeItem}/>
</Route>
<Route path="Offense" component={Offense}/>
</Route>
</Router>
I'm trying to get currently active route segment (ie Administrative or Offense).
Is there a way to do something like this? ie route constraints
<Router history={history}>
<Route path="/:segment" component={ReviewWizard}>
<IndexRoute component={Administrative}/>
<Route path="/:segment=Administrative/:itemId" component={Administrative}>
<Route path="/Administrative/:itemId" component={AdministrativeItem}/>
</Route>
<Route path="/:segment=Offense" component={Offense}/>
</Route>
</Router>
If not, what is best practice to get the current active route segment? I don't like this.context.router.routes[1].path

First off I would recommend the following router config, as it seems that it's what you're aiming for:
<Router history={history}>
<Route path="/" component={ReviewWizard}>
<!-- whenever we hit '/' we redirect to '/Administrative' -->
<IndexRedirect path="/Administrative"/>
<!-- Renders ReviewWizard <- Administrative -->
<Route path="/Administrative" component={Administrative}>
<!-- Renders ReviewWizard <- Administrative <- AdministrativeItem -->
<Route path="/Administrative/:itemId" component={AdministrativeItem}/>
</Route>
<!-- Renders ReviewWizard <- Offense -->
<Route path="/Offense" component={Offense}/>
</Route>
</Router>
As for detecting the currently active route (or if a route fragment is active), I would recommend using the router.isActive -method. Simply do something like this:
if (router.isActive('/Administrative')) {
doSomething()
} else if (router.isActive('/Offense')) {
doSomethingElse()
}
For something more declarative, I recommend just using the location object that react-router injects into each component it manages:
const { location: { pathname } } = this.props
const [ activeSegment ] = pathname.slice(1).split('/')
Hope these help!

Related

Component Missing when Nested inside of Route in React Router v6

When nesting the ChoosePlayer component inside a Route using React Router v6,
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/players">
<Route element={<ChoosePlayer />} />
// <--- Some dynamically generated routes here for /players/{playerName}
// These inner routes shows a modal in addition to ChoosePlayer in the background
</Route>
</Routes>
</BrowserRouter>
the ChoosePlayer component does not render when we are on the url http://localhost:3000/players or http://localhost:3000/players/reacher.
As a sanity check, ChoosePlayer component is rendered at http://localhost:3000/chooseplayer when we have
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/chooseplayer" element={<ChoosePlayer />} />
</Routes>
</BrowserRouter>
and at http://localhost:3000/players when index is added to its Route component, but this prevents ChoosePlayer from showing up at http://localhost:3000/players/reacher
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/players">
<Route index element={<ChoosePlayer />} />
// <--- Some dynamically generated routes here for /players/{playerName}
// These inner routes shows a modal in addition to ChoosePlayer in the background
</Route>
</Routes>
</BrowserRouter>
Why is it not rendering in the first example? Is there a way to do this in React Router v6? I think this approach works in React Router v5.
Thanks!
So I've gathered you want to render this ChoosePlayer component with the path is "/players" and also when on some "/players/*" path. In this case you are treating ChoosePlayer more as a layout component that renders a set of nested routes.
Issue
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/players">
<Route element={<ChoosePlayer />} />
// <--- Some dynamically generated routes here for /players/{playerName}
// These inner routes shows a modal in addition to ChoosePlayer in the background
</Route>
</Routes>
</BrowserRouter>
The ChoosePlayer route is missing a path for matching and rendering.
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/chooseplayer" element={<ChoosePlayer />} />
</Routes>
</BrowserRouter>
ChoosePlayer is matched and rendered, but isn't on a "/players/*" route and doesn't have any nested children routes.
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/players">
<Route index element={<ChoosePlayer />} />
// <--- Some dynamically generated routes here for /players/{playerName}
// These inner routes shows a modal in addition to ChoosePlayer in the background
</Route>
</Routes>
</BrowserRouter>
An an index route, ChoosePlayer is matched and rendered when the path is exactly "/players", but is excluded from being rendered when matching and rendering one of the other nested routes.
Solution
I suggest moving ChoosePlayer up into the root "/players" route and render an Outlet component for the nested routes to be rendered into.
Example:
import { Outlet } from 'react-router-dom';
const ChoosePlayer = () => {
// ...any component business logic...
return (
<div /* any container props/styling/etc... */>
{/* Common Choose Players UI */}
<Outlet /> // <-- nested routes render into here
</div>
);
};
...
<BrowserRouter>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/players" element={<ChoosePlayer />} >
// <--- Some dynamically generated routes here for /players/{playerName}
// These inner routes shows a modal in addition to ChoosePlayer in the background
</Route>
</Routes>
</BrowserRouter>
You can read more about layout routes here.

React router only show Navigation component if the current path is on any of the valid routes

For a invalid route, I want to show the NotFound component, but also not show the Navigation component:
const Layout: React.FunctionComponent = () => {
return (
<Router>
<Navigation />
<Switch>
<Route path="/explore" exact>
<ExploreIndex />
</Route>
<Route path="/explore/:id" exact>
<ExploreShow />
</Route>
<Route path="/" exact>
<Home />
</Route>
<Route component={NotFound} />
</Switch>
</Router>
);
};
If I go to /aaaaaaa, my NotFound component loads but so does my Navigation. How can I not have Navigation render for such routes?
What about just rendering it as another route?
<Route path={['/explore', '/explore/:id', '/']} exact component={Navigation} />
It will not be rendered if the route does not match any of the routes listed in the path array.
You can add NavigationBar in the specific components rather than app.js. So for example if there is a about page, place NavigationBar on top of the component

Costomize React Routing with Switch Statement

I am building a react app where two different Usergroups sign in (via Firebase).
Each Usergroup needs to get a different Routing. The different groups should share urls but with different content.
To do so I have added a switch statement to routes js.
When I change acctype manually the code works like expected, but I need to change the acctype var out of my firebaseclass in order to route the right person to the right route...
The problem is, that react renders the view before any setter Method can set the acctype variable. I have tried it with callbacks and .done and asnyc as well.
This routes.js exports the components with the variable rut directly into the index.js React.dom.render()
Thank you for your help!
import {Route, Router, IndexRedirect, browserHistory} from 'react-
router';
var acctype = 0;
var rut = "";
switch (acctype) {
case 0: //Group0
rut = (
<Router history={browserHistory}>
<Route path="/" component={Blank}>
<IndexRedirect to="/welcome"/>
<Route path="welcome" component={Welcome_View}></Route>
<Route path="login" component={Login_View}></Route>
<Route path="*" component={fofView}></Route>
</Route>
</Router>
);
break;
case 1: //Group1
rut = (
<Router history={browserHistory}>
<Route path="/" component={Main}>
<IndexRedirect to="/uebersicht"/>
<Route path="uebersicht" component={Uebersicht_KtppView}></Route>
<Route path="wiki" component={Wiki_KtppView}></Route>
<Route path="netzwerk" component={Netzwerk_KtppView}></Route>
<Route path="meineEinrichtung" component={meineEinrichtung_KtppView}></Route>
<Route path="feedback" component={Feedback_KtppView}></Route>
</Route>
</Router>
);
break;
case 2: //Group 2
rut = (
<Router history={browserHistory}>
<Route path="/" component={Main}>
<IndexRedirect to="/main"/>
<Route path="main" component={MainView}></Route>
<Route path="minor" component={MinorView}></Route>
</Route>
</Router>
);
break;
}
export default(rut)
I have found a new idea to solve this problem
the onEnter attribute does the work
It is described in the last tipp
https://scotch.io/tutorials/routing-react-apps-the-complete-guide

relative routing in react-router

Did anyone know how to create for any path that ends with '/popup-image-:id' ? i have website where each image could be opened in popup on any page. So, if i couldn't implement '/popup-image-:id' i have to double each route in my website to place inside. I would like avoid redundance and fragility.
my current routing:
<Router history={browserHistory}>
<Route path="/" component={Base}>
<Route path="profile" component={Profile}>
<Route path="popup-image-:id" component={Full_Piture} />
</Route>
<Route path="feed" component={Feed_List}>
<Route path="popup-image-:id" component={Full_Piture} />
</Route>
<Route path="user-:id" component={User_Page}>
<Route path="popup-image-:id" component={Full_Piture} />
</Route>
</Route>
</Router>
As u can see i had to produce a lot of duplicated code. If i could write something like <Route path="*/popup-image-:id" component={Full_Piture} /> it will be much cleaner and solid code
Is the parent <Route> also supposed to match? If it isn't, you should be able to use the ** syntax.
<Route path="/**/popup-image-:id" component={Full_Picture} />
If the parent <Route> should also match, you could create a <RouteWithPopup> component that returns a <Route> which has the <Route path='popup-image-:id'> as its child.
const RouteWithPopup = (props) => {
return (
<Route {...props}>
<Route path="popup-image-:id" component={Full_Picture} />
</Route>
)
}
Then you could turn your route config into:
<Router history={browserHistory}>
<Route path="/" component={Base}>
<RouteWithPopup path="profile" component={Profile} />
<RouteWithPopup path="feed" component={Feed_List} />
<RouteWithPopup path="user-:id" component={User_Page} />
</Route>
</Router>

React-router not matching on valid route

I cannot get this react router to match on second part of a path no matter what I do.
Express server is returning index.html for any URL match (I'm not getting a GET error on any URL so I assume this is fine)
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
});
Here are some examples of routes i've tried, which should be valid rules according to react router docs
Example 1 )
<Route path="test">
<IndexRoute component={Home} />
<Route path="/login" component={Login} />
</Route>
OR
<Route path="test">
<IndexRoute component={Home} />
<Route path="/login" component={Login} />
</Route>
http://localhost:3100/test = Success > Returns home component
http://localhost:3100/test/login = Fail > gives me blank screen
Example 2 )
<Route path="/login" component={Login} />
http://localhost:3100/login = Success > Returns login component
Example 3 )
<Route path="/test/login" component={Login} />
OR
<Route path="test/login" component={Login} />
http://localhost:3100/test/login = Fail > gives me blank screen
I'm using version 2.5, Any help would be much appreciated!
** Yarn dump of react router **
react-router#^2.5.0:
version "2.8.1"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-2.8.1.tgz#73e9491f6ceb316d0f779829081863e378ee4ed7"
dependencies:
history "^2.1.2"
hoist-non-react-statics "^1.2.0"
invariant "^2.2.1"
loose-envify "^1.2.0"
warning "^3.0.0"
Try path="login" instead of path="/login" . The slash before path is not needed in nested routes.
<Route path="test/">
<IndexRoute component={Home} />
<Route path="login" component={Login} />
</Route>
From express documentation, app.get('/*' uses regular expression. so, '/*' work for 0 to n '/'. Try:
app.get('/.*
/.* should resolve '/' + 0 to n caractères.
Regards
I think the problem lies more with the way you are rendering your app than react-router itself, since you are not getting a route not found message but a blank screen, I suggest the following.
when you create your history object do the following
import { useRouterHistory } from 'react-router';
import createBrowserHistory from 'history/lib/createBrowserHistory';
// ========================================================
// Browser History Setup
// ========================================================
const createHistory = (basename) => {
return useRouterHistory(createBrowserHistory)({
basename: basename
})
}
const history = createHistory('/test');
Your route configuration will then look like this
<Route path="/" component={App} >
<IndexRoute component={Home} />
<Route path="login" component={Login} />
</Route>
Your App component would then look something like this
export const App extends Component = {
render() {
return(
<div class='app-container'>
{this.props.children}
</div>
)
}
}
App.propTypes = {
children: PropTypes.element.isRequired
}
export default App;
You'll then be able to access and render the component Login # /test/login

Categories

Resources