Route from one component to another reactjs - javascript

I have my app like that
<Router>
<div className="App">
<Link to="/" style={{ textDecoration: "none" }}>
<header>Project Issues</header>
</Link>
<Switch>
<Route exact path="/">
<Issues />
</Route>
</Switch>
</div>
</Router>
Inside Issues component, I choose to render one of two components based on a window width condition, one of the two components is called TwoPagesLayout, in this component when the user clicks on some text, it should go to another component called IssueDetails.
Here's the part of the TwoPagesLayout component:
{issues.map((issue: any) => (
<div>
<Link to="/Details" style={{ textDecoration: "none" }}>
<p className="issue-title">{issue.title}</p>
</Link>
<hr></hr>
<Switch>
<Route exact path="/Details">
<IssueDetails issue={issue} />
</Route>
</Switch>
</div>
))}
The problem is when I click on the text, it goes to that url "http://localhost:3000/Details" but it appears as a blank white page, it doesn't render what is inside the page.
Hope I have made it clear, I am new to react so I think the question maybe sounds common.

<Route exact path="/">
<Issues />
</Route>
Since you've marked this as exact, once the url changes to /Details, it no longer matches, and so Issues unmounts. Since Issues unmounts, so too does its descendant IssueDetails. You probably want to do:
<Route path="/">
<Issues />
</Route>

The Issues component will only render on the "/" path. When the page is showing "/Details" the Issues component will not render, and that includes the nested Router.
For this reason (they’re confusing), I personally try to avoid nested routers, so I would suggest keeping all the Route components together unless you have a reason otherwise!

Related

React Router v5 always redirecting

I'm trying to handle unmatched routes in my app by having them redirect to the login screen, I've set my routes up like so:
<Switch>
{
session.IsLoggedIn === false &&
<Container fluid className="d-flex flex-column h-100">
<Route exact path="/" component={ Login } />
<Route path="/ResetPassword/:token" component={ ResetPassword } />
<Redirect to="/" />
</Container>
}
</Switch>
With this setup though, even if I enter a legitimate route, i.e /ResetPassword/3245924, it still redirects to the login screen.
Note: I've gotten the above setup by following this tutorial: https://www.surajsharma.net/blog/react-router-default-route
How would I ensure that the legitimate routes are hit while redirecting on non handled routes?
You doesnt have wrapped your redirect in default router, therefore it will be always rendered/triggered
for correct behaviour wrap it in "default" route
<Switch>
{
session.IsLoggedIn === false &&
<Container fluid className="d-flex flex-column h-100">
<Route exact path="/" component={ Login } />
<Route path="/ResetPassword/:token" component={ ResetPassword } />
<Route path="*"><Redirect to="/" /></Route>
</Container>
}
</Switch>
I figured the issue out, it seems to be because the <Container> element was housing the routes, not the <Switch> element. When I moved the <Switch> element into the <Container>, making the <Route> elements direct descendants of the element it worked.
Issue
The Switch component exclusively renders the first matching Route or Redirect component. When it hits anything other than one of these two components, i.e. the Container, it stops matching and just renders that component/element. Once not rendered directly by a Switch, all Route and Redirect components are inclusively matched and rendered. The Redirect component doesn't have a from prop so it will always be matched and effect a navigation change.
Solution
Since the Switch isn't rendering any Route or Redirect components it appears it's unnecessary where it is currently. Move it into the conditional rendering to directly wrap the routing components.
{!session.IsLoggedIn &&
<Container fluid className="d-flex flex-column h-100">
<Switch>
<Route path="/ResetPassword/:token" component={ResetPassword} />
<Route path="/" component={Login} />
<Redirect to="/" />
</Switch>
</Container>
}
Technically speaking, the path "/" is already a path-prefix for every other route path, so the Redirect isn't actually reachable. You should be able to remove it since path="/" will catch and match anything that wasn't already matched prior to it.
{!session.IsLoggedIn &&
<Container fluid className="d-flex flex-column h-100">
<Switch>
<Route path="/ResetPassword/:token" component={ResetPassword} />
<Route path="/" component={Login} />
</Switch>
</Container>
}
For best practice, all default paths should lead to your landing page...Routing during runtime is supposed to be managed by React backend. You could look into service workers for your own proxy. I suggest you remove the: session.IsLoggedIn === false && and just use a regular route initialization ...and use useState or onComponentDidMount to automatically load the content you want- you can make that page a component. oh my apologies for the confusion, I'm glad you got this resolved.

React Router is giving me a blank page

I am using the react router to create multiple webpages without changing my navbar and all it gives me is a blank page. I have tried multiple things such as a browser router, and switch and neither of them work.
function App() {
return (
<div className="App">
<Navbar />
<Router>
<Link to="/">Home</Link>
<Link to="/aggrid">Aggrid</Link>
<Route path="/" component={GhibliModal} />
<Route path="/aggrid" component={Aggrid} />
</Router>
</div>
);
}```
Well first things first, you need to wrap your whole App component with <BrowserRouter>, but I from what you said in the question, I would assume you already know that.
Secondly, you don't need the <Router> component. Read here.
From reading the documentation, all <Route> components must be wrapped in a <Routes> (note the 's' at the end) component.
And lastly, I'm pretty sure you cannot have <Link> components inside the <Routes> component.
Also, the component prop is now called element, so
<Route path="/" component={GhibliModal} />
should become
<Route path="/" element={<GhibliModal/>} />
You need to add <Outlet /> tag in the components that are loaded by Router.
I usually put it at the end of the JSX:
return (
<div>
<yourcodehere/>
<Outlet/>
</div>
)

What is best practice when it comes to react Microfrontend Architecture and React Router Best Practices

I am working on building a microfrontend POC in React using ModuleFederation
My question surrounds best practices when it comes routing ['react-router-dom v6']
Currently, I have my application split into 3 separate microfrontends: Shell, Container, Header
In my case, my Header needs access to the url params to be able to read params using useParams hook provided by react-router-dom
For this to happen, I must provide a path inside react router to have access
Header MFE
<Router>
<Routes>
<Route path="/stores/:storeId/:tabId/*" element={<Header />} />
</Routes>
</Router>
When I export this using ModuleFederation, I am currently omitting the wrapped router and just exposing the <Header /> so that the Container can provider the Router, etc
This is where I run into my conundrum...
My Header component will technically live outside the main router so that the Container can serve its routes and respective paths
Container MFE
<Layout style={{ minHeight: '100vh' }}>
<Header /> <== does not work / no access to params
<MainContent>
<Routes>
<Route
path="/stores/:storeId/dashboard"
element={<h3>dashboard</h3>}
/>
</Routes>
</MainContent>
</Layout>
Normally this would not be a problem except the fact that both the Header and dashboard component technically fall within the same route restricting me the ability to group in main route as seen below.
Duplicated routes
<Layout style={{ minHeight: '100vh' }}>
<MainContent>
<Routes>
<Route path="/stores/:storeId/:tabId/*" element={
<>
<Header />
<MainContent>
<Outlet />
<MainContent>
</>
}>
<Route
path="/stores/:storeId/dashboard"
element={<h3>dashboard</h3>}
/>
</Route>
</Routes>
</MainContent>
</Layout>
path="/stores/:storeId/:tabId/* <= header nav needs access to these params so it will only load if this route is matched
path="/stores/:storeId/dashboard" <= direct route in which :tabId equals dashboard in this case
I want the header to always be present
I experimented with this approach and it worked but it seems dirty:
<Layout style={{ minHeight: '100vh' }}>
<Routes>
<Route path="/stores/:storeId/:tabId/*" element={<Header />} />
</Routes>
<MainContent>
<Routes>
<Route
path="/stores/:storeId/dashboard"
element={<h3>dashboard</h3>}
/>
</Routes>
</MainContent>
</Layout>
Is this a bad practice or am I looking at it the wrong way and this is in fact okay to do?
Should I be exporting the <Header /> wrapped in its own routes?
After digging deeper into the documentation, it seems having many declarations is acceptable
React Router v6

routing within an app using react router to move to another page

I am trying to use router in my app
so I used react-router-dom, but I am facing issues,
researched and found this link but still not helping me.
Invariant failed: You should not use <Route> outside a <Router>
can you tell me how to use route and link
i need to redirect to another page.
providing my code snippet and sandbox below.
https://codesandbox.io/s/still-smoke-uf731
let Channel = ({ channelName, channelString, onClick, active }) => (
<div onClick={onClick} className=" col-lg-2 col-md-4 col-sm-6 ">
<div>router</div>
<Router>
<Link to={"/here"}> here</Link>
<Switch>
<Route path="/auth" />
<Route path="/" />
</Switch>
</Router>
<div
className="channel-button"
style={{
backgroundColor: active === channelString ? "orange" : ""
}}
>
<p>{channelName}</p>
</div>
</div>
);
Use exact as an attribute in your home route like the following code.
<Router>
<Link to={"/here"}> here</Link>
<Switch>
<Route exact path="/" />
<Route path="/auth" />
</Switch>
</Router>
I checked your sandbox. Looks like a good start, but you messed some things up.
Here is my fork of your sandbox: https://codesandbox.io/embed/staging-fast-rr5k9
First, don't put react components in the containers, put them in the components folder and import them.
What was going on was, that you had brand new <Router> for every page you had. So I pulled the Router out. Its also not imported correctly. It should be
import { BrowserRouter as Router } from "react-router-dom";
So you pretty much need something like this
<div>
<Link to={"/bbc-news"}>BBC</Link>
</div>
<div>
<Link to={"/cnbc"}>CNBC</Link>
</div>
<Switch>
<Route
key={"fbbc-news"}
path="/bbc-news"
render={p => <Channel channelName="BBC" channelString="bbc-news" />}
/>
<Route
key={"cnbc"}
path="/cnbc"
render={p => <Channel channelName="CNBC" channelString="cnbc" />}
/>
</Switch>
</Router>
Where Channel component renders whats inside the channel. the key in Route is important, because it makes React properly trigger componentDidMount, which calls the thunk action which fetches (that one is perfect).
Then to access the results from fetch, which you have placed in Redux =>
const mapStateToProps = state => ({ json: state.json });
You don't need a lot of the things you had, so I have removed them, like the onClick, which was trying to do react routers job
You can try this:
import Stats from './containers/stats';
<Route
exact={true}
path="/"
component={Stats}
key="Mykey"
/>

How to use routes in two different components - ReactJS

I am creating an application using ReactJS. I am using react router v4 from react-router-dom.
I have written routes in index.js file.
<BrowserRouter>
<Switch>
<Route exact path="/" component={Login} />
<Route exact path='/dashboard' component={Viewport} />
</Switch>
</BrowserRouter>
Rest of the application in Viewport.js file.
return (
<div className="">
<Sidebar navigation={this.viewport} />
<HeaderBanner user={this.props.user} />
<div className="center-panel">
//todo
//Can I use router here?
</div>
</div>
)
After user login's, I am rendering Viewport which contains Sidebar and header bar by default. Based on the item click in the sidebar navigation, I need to render components dynamically. As of now, if I write anything in the place of todo, it renders only that component for the complete browser window.
Is there any way to use routers in multiple places of the application? If yes, how can I implement it? If no, what's the best solution?
As far as I have seen, routers will be stacked at one place in the application.
Thanks in advance.
I followed a tutorial on youtube recently which was very useful
So I took some of it and applied it to your setup
<BrowserRouter>
<div>
<Route exact path="/" component={Login} />
<Route exact path='/dashboard' component={Viewport} />
</div>
</BrowserRouter>
import { NavLink, Route } from 'react-router-dom';
class Viewport extends Component {
constructor(props) {
super(props);
}
render() {
return (
<div>
<div className="Side-bar">
<NavLink
activeClassName="active"
to={`${this.props.match.url}/sub-page-name-1`}>Sub Page 1</NavLink>
<NavLink
activeClassName="active"
to={`${this.props.match.url}/sub-page-name-2`}>Sub Page 2</NavLink>
<NavLink
activeClassName="active"
to={`${this.props.match.url}/sub-page-name-3`}>Sub Page 3</NavLink>
</div>
<HeaderBanner user={this.props.user} />
<div className="center-panel">
<Route path={`${this.props.match.url}/sub-page-name-1`} component={SubPagePanel1} />
<Route path={`${this.props.match.url}/sub-page-name-2`} component={SubPagePanel2} />
<Route path={`${this.props.match.url}/sub-page-name-3`} component={SubPagePanel3} />
</div>
</div>
)
}
}
I removed Switch as well because I didn't use it for my sub pages... :-S
Update: Have created a repo showing a working example of sub page content
https://github.com/PocketNinjaDesign/so-sub-routes-answer
Yes you can use <Routes> in as many places as you want. <Router> components are the ones you can only use once.

Categories

Resources