React Router: Changing components and routes by button - reactjs

In a React application, there is a page with 2 buttons. Each button renders a different component, however, the route/URL doesn't change. How can I change the route, only changing the grey area? and How can I change the state if the user goes directly to the URL?
https://codesandbox.io/embed/elastic-fog-7hqk9?fontsize=14&hidenavigation=1&theme=dark

Yes, you can use Switch, it will render your component in case it matched the URL. Here is an example:
<Container>
<Header /> // this will render in all cases (Fixed here for example)
<Switch>
<Route exact path="/component1" component={Component1} />
<Route exact path="/component2" component={Component2} />
</Switch>
</Container>

Related

react router / i wanna go to a new page instead of adding the component under the mother component

when i click on order button i wanna go to a new page instead o staying on Buying form component and adding orderComplited component down of it
BuyForm.js
App.js
orderCompleted
The issue is that you are rendering your OrderCompleted route as a nested route with the Outlet being rendered by the BuyForm route.
<Route path="order" element={<BuyForm />}>
<Route path="orderCompleted" element={<OrderCompleted />} />
</Route>
The BuyForm component is a layout component. This means the BuyForm component remains on the screen rendered while subroutes are also matched and rendered.
To resolve you should refactor the code a bit. Move the BuyForm component into its own route which will be designated as the index route to be matched and rendered when the layout Route components path matches. Remove the Outlet from BuyForm, one will be rendered by default now by the wrapping Route. Now both the BuyFormandOrderCompletedroutes will be rendered into theOutlet, one at-a-time, when their path`s match.
<Route path="order">
<Route index element={<BuyForm />} />
<Route path="orderCompleted" element={<OrderCompleted />} />
</Route>

React: When navigating away from mounted component, show it again if click browser back button

Here is a part of my root component code:
const App = () => {
return (
<Switch>
<Route path="/products">
<AllProducts />
</Route>
<Route path="/teams">
<AllTeams />
</Route>
<Route exact path="/">
<Home />
</Route>
</Switch>
{isVisible && (
<Overlay />
)}
);
};
I have a Home component, from where I can navigate to other pages using a router. In Home component I have a button and when clicking on it, I set isVisible variable to true and <Overlay /> component is being opened as an overlay (similar to modal) and when it's open, the / pathname does not change, because it's outside router. There may be many links and I can navigate to other routes, for example /teams and also go much more deeper away from it. And the question is, if I hit the browser back button at some point, how to show this <Overlay />, like it were in the browser history?
Add it as a query param.
A query string is a part of a uniform resource locator (URL) that assigns values to specified parameters.

React Router, Page Not Found handling

I have this setup for my routes:
<Container>
<Input />
<Switch>
<Route path='/' exact component={LatestMovies}/>
<Route path='/movie/:id' component={MovieWithDetails}/>
<Route component={PageNotFound}/>
</Switch>
</Container>
1.How would I need to setup the router, so that the Input component would be visible with all other components inside the Switch, except for the PageNotFound component?
I know that I could add the Input component inside the other components manually, but was wondering if there was a better way?
2.Inside the MovieWithDetails component I'm using fetch, where I fetch for a movie with an id, which I get from clicking on a link from the LatestMovies component through the router props.
The link, and any id can also be manually typed, so I was wondering, how would I need to handle the showing of PageNotFound component here?
1 - Did you try with multiple components? Something like:
<Switch>
<Input/>
<Route path='/' exact component={LatestMovies}/>
<Route path='/movie/:id' component={MovieWithDetails}/>
</Switch>
<Switch>
<Route path='/somepath' component={PageNotFound}/>
</Switch>
2 - I think that it's subjective. In my opinion I would show a feedback saying that there's no movie with the typed ID and I would not redirect to the PageNotFound component. But if you want to do it, with a simple `this.props.history.push('/somepath') will be right

location.pathname vs router

I am still learning react router v4. and I'd like to know what exactly is the difference between doing this
getting location using
const {
match,
location,
layoutBoxed,
navCollapsed,
navBehind,
fixedHeader,
sidebarWidth,
theme,
} = this.props;
Option 1
if(location.pathname === '/500'){
return <Page500 />
and this
Option 2
<Route path={'/500'} component={Page500} />
As for me, while the first option displays everything properly for me,
the 2nd one i.e. the router one, shows the component in only half the page.
Now, why is that happening?
Option 1 result -->
Option 2 result -->
But the main point--> what is the difference between using location.path name and router
In Option 2 <Route path={'/500'} component={Page500} />
Here you are creating a Route which has a path of /500 and loads a component Page500. This means that when the user navigates to the path specified in the Route, React-Router will render the component where the Route was defined.
In Option 1 ,
if(location.pathname === '/500'){
return <Page500 />
}
the parent component decides when to render the Page500 component, based on the location prop which it receives. This location prop would ultimately be coming from a Route or the withRouter HOC. This is equivalent to
<Route render={(props)=>{
if(props.location.pathname === '/500'){
return <Page500 />;
}else{
return null;
}
}
}
/>
which can also be written as
<Route path={'/500'} component={Page500} />
So to sum it up, you can only do Option 1 if you get the location prop from the parent component, you can define a Route (Option 2) anywhere in the application.
Edit:
If you have all your Routes like
return( <div>
<Route path={'/500'} component={Page500} />
<Route path={'/confirm-email'} component={PageConfirmEmail} />
<Route path={'/lock-screen'} component={PageLockScreen} />
<Route path={'/login'} component={PageLogin} />
<Route path={'/sign-up'} component={PageSignUp} />
<Route path={'/forgot-password'} component={PageForgotPassword} />
<Route path={'/fullscreen'} component={PageFullscreen} />
</div> );
you are running the risk of multiple Routes rendering which might be why you are getting half page render in Option 2. To prevent that from happening and only render the first Route that matches, you should add a Switch
return( <div>
<Switch>
<Route path={'/500'} component={Page500} />
<Route path={'/confirm-email'} component={PageConfirmEmail} />
<Route path={'/lock-screen'} component={PageLockScreen} />
<Route path={'/login'} component={PageLogin} />
<Route path={'/sign-up'} component={PageSignUp} />
<Route path={'/forgot-password'} component={PageForgotPassword} />
<Route path={'/fullscreen'} component={PageFullscreen} />
</Switch>
</div> );
More on Switch can be found at https://reacttraining.com/react-router/web/api/Switch
One of the main features with react router is that you can do stuff such as:
<Route path="/user/:id" component={User} />
and id will be passed into User component.
Ex. /user/bob and /user/jill will both render a User component, but in your componentDidMount you can now fetch the correct user information from your API.
With location.pathname that task becomes more convoluted as #palsrealm mentioned. But first of all, the location prop must be available for this method to work.
There are other features that you would be losing out, but that is the main one I can think of so far. You can check out the Route api documentation here.
EDIT: As for why it is rendering differently, I really can't answer without more context. For example, is the Route wrapped in a Switch component like so:
<Switch>
// Other routes
<Route exact path="/500" component={Page500} />
</Switch>

React-router: never unmount a component on a route once mounted, even if route change

I have a React application that declares some routes :
<Switch>
<Route exact path={'/'} render={this.renderRootRoute} />
<Route exact path={'/lostpassword'} component={LostPassword} />
<AuthenticatedRoute exact path={'/profile'} component={Profile} session={session} redirect={'/'} />
<AuthenticatedRoute path={'/dashboard'} component={Dashboard} session={session} redirect={'/'} />
<AuthenticatedRoute path={'/meeting/:meetingId'} component={MeetingContainer} session={session} redirect={'/'} />
<Route component={NotFound} />
</Switch>
(AuthenticatedRoute is a dumb component that checks the session, and either call <Route component={component} /> or <Redirect to={to} />, but at last, component method is invoked)
Where basically each component is mounted/unmounted on route change. I'd like to keep that aspect except for the Dashboard route which does a lot of things, and that I would like to be unmounted once not on dashboard (let's say you arrive on a meeting page, you do not need to mount your dashboard yet) but once you loaded once your Dashboard, when you go on your profile page, a meeting or whatever, when you go back on your Dashboard the component does not have to mount again.
I read on React-router doc that render or children might be the solution, instead of component, but could we mix routes with children and other with component? I tried many things and never achieved what I wanted, even with render or children, my Dashboard component is still mounting/unmounting.
Thanks for your help
The Switch component only ever renders a single route, the earliest match wins. As the Dashboard component is inside it, it gets unmounted whenever another route gets matched. Move this Route outside and it will work as intended with render or children.

Resources