Adding component to page when more specific route is used - reactjs

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.

Related

How to remove unhandled path URL from ReactJS

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} />

Can React Router make multiple Routes visible at once and encoded in URL at once (desirable solution not failure)?

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}/>
</>

React Router, 2 routes with similar urls

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}/>

How do I avoid rendering a component when another component in a similar path has already rendered when using URL params in React Router v4?

I'm trying to create RESTful routes for my application, but I'm having problems when it comes to routes with URL params.
Here are the routes that I want to have:
/accounts
/accounts/new
/accounts/edit
/accounts/:id
These is what my router looks like:
<Router>
<Route exact path="/accounts" component={AccountsList} />
<Route exact path="/accounts/new" component={AccountCreate} />
<Route exact path="/accounts/edit" component={AccountUpdate} />
<Route exact path="/accounts/:id" component={AccountDetail} />
</Router>
/accounts works fine, but when I go to /accounts/new or /accounts/edit, it also renders AccountDetail which is supposed to be located at /accounts/:id.
For the record, that I get that this is the correct behavior since /accounts/:id technically matches /accounts/new and /accounts/edit.
My question is if there's a way to make :id match with a specific pattern only (numbers only).
Try the < Switch> component of reactRouter.
Renders the first child < Route> or < Redirect> that matches the
location.
I think it's exactly what you are looking for.

How does OKCupid, Reddit handle user profile routing with react router?

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')
}

Resources