Issue with connected-react-router - react-router

I have created the following routes using connected-react-router as shown below
<Switch>
<Route exact={true} path="/a" component={A}/>
<Route exact={true} path="/b" component={B}/>
<Route path="/c/:id" component={C}/>
</Switch>
But when I hit the url my.domain.com/c, the component does not get render. But when I go and give the url my.domain.com/c/12, then it works. I have tried setting exact={false} as well. Still it does not work. Any help will help me proceed further.

When you declare the route:
<Route path="/c/:id" component={C}/>
You are saying that the "id" it's mandatory. If you need render the page even if the user don't pass the id, you need to add "?":
<Route path="/c/:id?" component={C}/>

Related

How to have react route path one/two/three?

I would like to have something like this
<Route
path="/one/two/three"
render={() => (
<Component/>
)}
exact
/>
But it does not seem to work locally when I wrap it all into a Router. I only see the contents of the Component when it is just /one, but I would like to have /one/two/three as the path (being my root - user lands on that path).
In react-router-v4 you can have below routes only,
<Route path="/one" render={() => (<Component/>)} exact /> //Direct route without any params
or
<Route path="/one/:two" render={() => (<Component/>)} exact /> //Route with params, here `:two` is the parameter to route
If you want to use routes like in your example, then this can be achieve using BrowseRouter basename attribute,
<BrowserRouter basename="/one/two">
<Route path="/three" render={() => (<Component/>)} exact />
</BrowserRouter>
And you Link should be like,
<Link to="/three"/> // renders <a href="/one/two/three">
Few reasons why this did not work for me.
I was missing output: { publicPath: '/' }, in my webpack config.
And weirder thing was that I was using PureComponent instead of Component which totally broke the rending when redirecting to the next step with similar path(x/y/z) or using Link.

react router query parameters changed component will unmount

When query parameters changed, the same component will unmount and then mount.for example:
I have a url like /admin and also have a component called Admin. In Admin, there are some inputs for searching. I add a query parameters after /admin like /admin?userId=123.The componet's componentDidMount will excute again. Is there any way to prevent this?
and setting likes this
export default function (history, app) {
return (
<Switch>
<Route exact path='/admin/settings/user' component={getComponent(User,app,userModel)} />
<Route path='/admin/settings/user/:id' component={getComponent(UserEdit,app,userModel)} />
<Route path='/admin/settings/role' component={getComponent(Role,app,roleModel)} />
<Route path='/admin/settings/menu' component=
</Switch>
)
}
getComponent is a layload component.
#Alex Brazh I used v4 and the router likes this;
<Router>
<Switch>
<Route exact path='/' component={getComponent(Login,app,loginModel)}/>
<Route path='/admin' render={ props => (
<Layout>
{ settings(history, app) }
</Layout>
)}/>
<Route path='/finance' render={ props => (
<Layout>
{ finance(history, app) }
</Layout>
)}/>
</Switch>
</Router>
You can use the URL interface to set query string values without unmount and mount your components:
const queryStringValue = 'bar'
const url = new URL(window.location.toString());
url.searchParams.set('foo', queryStringValue);
window.history.replaceState(null, '', url.toString());
Also, this solution won't add a new item in browser navigation stack

In react router 4, how does one negate a route / path using regex?

Say i have a route switch statement like the following:
render () {
<pre>
<Switch>
<Route path="/foo" render={render}>
<Route path="/bar" render={renderBar}>
<Route path="/" render={renderHome}>
{/* How do i express everything except the home page ?*/}
<Route render={renderFourOhFour}>
</Switch>
</pre>
}
How do i write a route that excludes everything except the home page given the above example? Do i just write a regex? If so i've tried something like
path={^(?!.*(home))}
with the regex react router v4 tester: https://pshrmn.github.io/route-tester/#/
You can use the render method on the Route, which gets passed the location as a prop. So:
<Route render={({location}) => {
return location.pathname !== '/' ? <p>Not home</p> : ''
}} />
1) It will be visible everywhere except /home
<Route path={/\/(?!home)/} component={Component} />
2) Everywhere except /
<Route path={/^.{2,}$/} component={Component} />
In react router 4, there isn't a explicit way to. I had redesign it in a way that the switch statement as a stack or queue.
It'll match the first few route components as the first choices and you'll have to place the last item as the default.
For example:
<Route path="/" exact component={Home}/>
<Route path="/will-match" component={WillMatch}/>
<Route component={NoMatch} />

How to differentiate between routes with same path but different params in react-router?

I have following as part of my react-router configuration:-
<Route path="/articles" component={articles}>
<Route path="/articles/:featureName" component={articleFeatures} />
<Route path="/articles/:slug" component={articleContent}/>
</Route>
So my links are going to be somewhat like this:-
/articles/sports/ (Feature Name)
/articles/euro-cup-2016 ( Slug)
The content for both the above pages are different. So how should I approach this?

Call stack exceeded when using react-router in an auth pattern

I'm using react-router rc6 in the following auth pattern:
const isLoggedIn = false
function requireAuth (nextState, replaceState) {
console.log(nextState.location.pathname)
if(!isLoggedIn) {
replaceState({ nextPathName: nextState.location.pathname }, '/login')
}
}
ReactDOM.render((
<Router history={browserHistory}>
<Route path='/' component={Main} onEnter={requireAuth}>
<Route path='login' component={Login} />
</Route>
</Router>
), document.getElementById('app'));
I've seen this as a common pattern, but according to https://github.com/rackt/react-router/issues/2773, I can't redirect in an onEnter hook because the function requireAuth above gets called in an infinite loop. How should I do it instead? I want to redirect to the /login page if not authenticated.
This is because the / onEnter handler tries to redirect to a route that executes the same / onEvent handler.
I.e. what happens is:
Router tries to handle request to / (first match of /login).
/ has an onEnter handler. Handler is executed.
Handler wants to navigate to /login.
Router tries to handle request to / (back to step 1).
So as you can see, the reason why you are getting a call stack exceeded error is because it is circular.
Try to change your routes to the following:
ReactDOM.render((
<Router history={browserHistory}>
<Route path='/' component={Main}>
<Route path='/login' component={Login} />
<Route path='/user' onEnter={requireAuth}>
<Route path='/profile' component={Profile}>
</Route>
</Route>
</Router>
), document.getElementById('app'));
This way only the routes that require authentication are protected behind your requireAuth handler.
If you'd rather have a simple auth solution for React, take a look at the React SDK for Stormpath that I've built.
It will take care of all of this. And instead of having to use hacky onEnter handlers, all you need to do is use the SDK's AuthenticatedRoute. E.g.
<Router history={createBrowserHistory()}>
<HomeRoute path='/' component={MasterPage}>
<IndexRoute component={IndexPage} />
<LoginRoute path='/login' component={LoginPage} />
<LogoutRoute path='/logout' />
<Route path='/verify' component={VerifyEmailPage} />
<Route path='/register' component={RegisterPage} />
<Route path='/forgot' component={ResetPasswordPage} />
<AuthenticatedRoute>
<HomeRoute path='/profile' component={ProfilePage} />
</AuthenticatedRoute>
</HomeRoute>
</Router>
The example above is a real-world example extracted from the React SDK example project. See: https://github.com/stormpath/stormpath-express-react-example/blob/master/src/app.js#L11-L23.
Let me know if this helped you.