I am trying to set up a similar structure, where /profile takes you to your profile and allows you to edit your info. /profile/:userId will take you to someone else's profile, and allow you to send messages but not edit (obviously). I am thinking something similar to this logic:
<Route path='profile'>
<IndexRoute component={requireAuth(Profile)} />
<Route path=':userId' component={requireAuth(Profile)} />
</Route>
and in the Profile component, do something like
if (this.props.params.userId !== this.props.currentUser.id)
<SendMessage toUser={this.props.params.userId} />
This gets cumbersome as there will be a ton of validation checks for pretty much every element on the page whether it's the current user or another profile. Is there a 'correct' way to do this?
Yes. The components for your own profile page (/profile) and the others page (/profile/:userId) should be different components (with maybe similar markup). The component for /profile for example need not have the <SendMessage/> etc.
<Route path='profile' onEnter={requireAuth}>
<IndexRoute component={ProfileSelfComponent} />
<Route path=':userId' component={ProfileOtherComponent} />
</Route>
The requireAuth will handle whether the user is logged in etc.
The only thing you want is that when a user tries to navigate to his own /profile/:profileId it routes back to his own profile
This can be done by adding something like this to the ProfileOtherComponent
componentWillMount(){
if (this.props.params.userId === this.props.currentUser.id)
browserHistory.push('/profile')
}
Related
Disclaimer: I'm pretty sure this is a duplicate, because there's no way no one asked this, but I don't know if i searched the wrong terms or so but I couldn't find an answer, so I'll ask here.
I'm using React routers (react-router-dom), so for example if I set:
<Route path='/home' component={Home} />
At this point, obviously, if I go to localhost:3000/home it will load my homepage, right?
But if I go to localhost:3000/fjnisodjuhfosij (just random text) it will load anyway a blank page, it won't say something like "this page doesn't exist" or just redirecting to the home.
How can I handle this? Thank you
Just add Route with path '*':
<Route path='*' component={YourComponent} />
To direct to home: Add this as the last route in switch: <Route><Redirect to="/home"/></Route>
Or, to show a 404 error page: Create a component for the error page (NotFound lets say) and add it as the last route: <Route component={NotFound} />
React router has the usual code:
<Switch>
<Route exact path='/order/:id' component={() => <OrderPage/>}/>
<Route exact path='/schedule/:orderid/:piececode' component={SchedulePage}/>
<Route path='/login' component={LoginForm}/>
<Route path='/about' component={About}/>
<Route path='/sales/invoicelist' component={InvoiceListPage}/>
<Route path='/sales/invoice' component={InvoicePage}/>
</Switch>
which facilitates, that one component (as specified in the Route that corresponds to the current URL) is instantiated and made visible in the React app.
But one can image the use cases when several root-level components should be made visible/available at once, like:
Multi-tab applications: the user wants to work with multiple invoices at once and she is opening multiple invoices in the app-level-tabs (not browser level) - each invoice in each page. So, she can keep editing one invoice while looking data from the other invoice. At the end of the session the use copies URL and sends via email to the collegue - she expects that collegue will be able to open the eaxact those pages;
stock trading application with multiple visible componens - share prices, data entry components for multiple stocks etc.
Does React Route has the capability to shoe multiple compoents and once and accept the URL which is concatenation (or some other combination) or multiple routes?
I have searched SO for this and there are similar questions, but all of them perceive such situation as the failure, e.g. they start to use Switch to show only one component.
Does React Router has capability for multiple visible routes and how such capability can be used?
Sure, let's take for example
<Route exact path='/order/:id' component={() => <OrderPage/>}/>
Your component OrderPage can have nested Route & Switch
const OrderPage = () => {
return (<>
<div>
....
</div>
<Switch>
<Route exact path='/order/:id/tab1' component={Tab1}/>
<Route exact path='/order/:id/tab2' component={Tab2}/>
</switch>
</>)
}
And to have this to work, and properly propagate url params, you need to remove the exact prop on your first route, and have all available url in your main route path
<Route path={['/order/:id/tab1', '/order/:id/tab2', '/order/:id']} component={OrderPage}/>
The correct answer is NO. Through react-router you can not have multiple concatenated URL's at the same time to render multiple pages.
But this can be achieved by designing the routes in a proper way such as for the example
Multi-tab applications: the user wants to work with multiple invoices
at once and she is opening multiple invoices in the app-level-tabs
(not browser level) - each invoice in each page. So, she can keep
editing one invoice while looking data from the other invoice. At the
end of the session the use copies URL and sends via email to the
collegue - she expects that collegue will be able to open the eaxact
those pages;
<Route exact path={['/order/:id/', '/order/:id/:refenceId']} component={() => <InvoicePage/>}/>
In this case, you can check if URL has referenceId then render the referenced invoice.
OR
By using query-paramters.
https://reactrouter.com/web/example/query-parameters
Add the referencedId in the query param and that can be shared
Through query-param it can even support your second usecase.
Switch component renders only one child route that matches current location. So if you want to render multiple Route components that match current location at once, you have to omit Switch.
For example, if you want both SalesPage and InvoicePage being rendered for /sales/invoice path you could do the following:
<>
<Route path='/sales' component={SalesPage}/>
<Route path='/sales/invoice' component={InvoicePage}/>
</>
My problem is that i cant figure out the best way to handle multiple dynamic params in a deep link without having to have it fully rely on the order of the Routes in the JSX
I'll start by outline the flow of my app.
List of Television Series -> user clicks series -> List of Episodes in Series -> user clicks episode -> Show stats about episode
after this flow, i want my path to be /series/:series_id/episode/:episode_id.
Currently i have this working by setting up my router basically like so:
<Router>
<Switch>
<Route exact path="/series" component={SeriesLibrary} />
<Route
path="/series/:series_id/episode/:episode_id"
component={Episode}
/>
<Route path="/series/:series_id" component={EpisodeLibrary} />
</Switch>
</Router
but that is relying on the multi-dynamic path (the one with the series_id and episode_id) coming before the one that just has the series_id!
This is because even when the path is series/4356/episode/4567 it would match the series/4356 before ever rendering the Episode component.
Is there a better way for me to address the issue of multiple dynamic deep linked params in react router?
I feel like this cannot be best practice, relying strictly on the order of JSX elements for your app to work?
You can pass exact prop to to EpisodeLibrary:
<Router>
<Switch>
<Route exact path="/series" component={SeriesLibrary} />
<Route exact path="/series/:series_id" component={EpisodeLibrary} />
<Route
path="/series/:series_id/episode/:episode_id"
component={Episode}
/>
</Switch>
</Router>
What I'm trying to do is to display User details next to the table of users.
The user table is displayed on /users route and when I go to /users/0 I want to display both, the user table, and component User with the user's details.
Here is what I tried to do: https://codesandbox.io/embed/react-router-redirects-typescript-fg8yf
This, however, displays only a blank page when I try to navigate to the user's details.
Can anyone explain to me what I'm doing wrong, please?
You have provided exact prop here,
<Route exact path="/users" component={Users} />
When you provide exact prop, it will only match the path /users and not anything else. So when you give path /users/0 it will not navigate, because there is no matching Route present.
You need to remove the exact prop,
<Route path="/users" component={Users} />
Read more about exact prop.
I have the following 2 routes:
<RouteEx path="/:id" component={Page2} />
<RouteEx path="/imprint" component={Imprint} />
Every time I click on imprint to navigate to my imprint page, I get an error in my console from Page2 component. How do I prevent calling Page2 when I want to navigate to Imprint page?
The "Route Matching" section of the React-Router documentation provides some tools for dealing with routes that can both serve as matches to the address text. The first is <Switch>, which makes it so that only one route--the first match, even if there are many--responds to the route match. Another is the exact property, which guarantees that a route won't be flexibly interpreted. In your case, you might use them both (though I think the exact tag may not be necessary in your case):
<Switch>
<RouteEx exact path="/imprint" component={Imprint} />
<RouteEx path="/:id" component={Page2} />
</Switch>
In this configuration, if the route matches '/imprint', it will not trigger the '/:id' route. This will work even if the id is a string. (Naturally, you'd have to make sure that you never encounter the case id === 'imprint'.)
If id is a number, then you can try using Regex :
<RouteEx exact path="/:id(\d+)" component={Page2}/>
<RouteEx exact path="/imprint" component={Imprint}/>