React nested routing problem (cannot displayed the child component) - javascript

I am new to react development. And I want to implement the routing mechanism in my page.
For example, there's component contains routes with the <Home /> and <Login /> component.
function App() {
return (
<div className="App">
<Switch>
<Route exact path="/home">
<Home />
</Route>
<Route path="/login">
<Login />
</Route>
</Switch>
</div>
);
}
The <Home /> component contains a <Navbar /> and a <Switch /> with two <Route />:
Home.js
function Home() {
return (
<div>
<Navbar />
<div>
<Switch>
<Route exact path={`/home`}>
<Menu />
</Route>
<Route path={`/home/temperature`}>
<div>temperature</div>
</Route>
</Switch>
</div>
</div>
)
}
However, I defined the <Link /> in the <Menu /> component as below:
function Menu() {
return (
<div>
<li>
<Link to={`/home/temperature`}>temperature child page</Link>
</li>
</div>
)
}
Originally, the page would displayed the <Home /> component with <Menu /> and <div> temperature </div>
I expected that when I clicked the link (<Link to={/home/temperature}>temperature child page</Link>) then it would replace the <Menu /> component with the only the <div>temperature</div> (Dispalyed the <Navbar/> and <div>temperature</div>, but it could not display anything.
How should I correct it?
Solution:
I finally figure out why I cannot get child component in my js script.
Firstly, I need to wrap the <Switch> with <Router> in <App> component.
Then, by reference this , I realized that I should not specify the exact in <Route path="/home"> to make sure that the nested route can work as well.
function App() {
return (
<div className="App">
<Router>
<div>
<Switch>
<Route path="/home">
<Home />
</Route>
<Route path="/login">
<Login />
</Route>
</Switch>
</div>
</Router>
</div>
);
}

simple routing
<Router>
<Switch>
<Route path={"/home"} exact component={Home} />
</Switch>
</Router>
nested routing
<Router>
<Switch>
<Route path={"/home"} exact component={Home}
<Rout path={"/temperature"} exact component={Temperature} />
</Route>
</Switch>
</Router>
`

Related

react-router-dom v6 rendering new page over current page

the problem is the following. in the app.js is spelled out Routes and the home component. the home contains a navbar that navigates the site, only if you go to any page, it is drawn on top of the home. And if you switch to the home itself, it will be duplicated. Articles on the internet did not help, as did the addition of exact in route path.
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home/>}/>
<Route path="/settings/" element={<Settings/>}/>
<Route path="/login/" element={<Login/>}/>
<Route path="/register/" element={<Register/>}/>
</Routes>
<Home/>
</div>
)
home
export default class Home extends Component {
render() {
return (
<div>
<NavBar/>
<ChatMenu/>
</div>
);
}
}
an example of how it is written in the navbar
export const NavBar = () => {
return (<div className="navbar-cm">
<div className="nav_element">
<Link to="/home">
<img src={homeIMG} className="nav_element"/>
</Link>
</div>
and a few more similar ones
</div>);
};
Issue
You are rendering the Home component again once outside the routes, this is why it's rendered with all routes including twice when on the "/home" path that renders Home.
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home />} />
<Route path="/settings/" element={<Settings />} />
<Route path="/login/" element={<Login />} />
<Route path="/register/" element={<Register />} />
</Routes>
<Home /> // <-- always rendered below routed content
</div>
)
}
Solution
Remove the Home component that is out on its own outside the routes.
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home />} /> // <-- now only Home component rendered
<Route path="/settings/" element={<Settings />} />
<Route path="/login/" element={<Login />} />
<Route path="/register/" element={<Register />} />
</Routes>
</div>
)
}
Remove <Home /> from the router:
function App() {
return (
<div className="messenger">
<Routes>
<Route path="/home/" element={<Home/>}/>
<Route path="/settings/" element={<Settings/>}/>
<Route path="/login/" element={<Login/>}/>
<Route path="/register/" element={<Register/>}/>
</Routes>
</div>
)

How to 1). put a div , 2). render a component without Route inside <Routes> with React Router in v6 React?

I want to put a div inside <Routes> and also Render a <Topbar /> and <Sidebar /> component inside <Routes> without <Route> tag for them.
My code is as follows:-
const App = () => {
return (
<Router>
<Routes>
<Route path="login" element={<Login />} />
<Topbar />
<div className="container">
<Sidebar />
<Route path="/" element={<Home />} />
<Route path="users" element={<UserList />} />
</div>
</Routes>
</Router>
);
};
I want to implement <Topbar /> and <Sidebar /> for all the routes.
But for an exception of login Page (Topbar and Sidebar should not be shown on the login page).
That's why I had put login Route at the top of Topbar and Sidebar.
The console is showing error as:
Uncaught Error: [Topbar] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
How to implement this functionality?
In react-router-dom v6 only Route and React.Fragment components are valid children for the Routes component.
Use layout components to render the Topbar and Sidebar components along with an Outlet for nested routes for the routes you want to render these components.
Example:
import { Routes, Route, Outlet } from 'react-router-dom';
const Layout = () => (
<>
<Topbar />
<div className="container">
<Sidebar />
<Outlet />
</div>
</>
);
const App = () => {
return (
<Router>
<Routes>
<Route path="/login" element={<Login />} />
<Route element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="users" element={<UserList />} />
</Route>
</Routes>
</Router>
);
};
Change your routes like below,
you need to check whether user is logged in or not, if user logged in use Tobbar, Sidebar etc, otherwise just return login route
const App = () => {
const [isLogin, setIsLogin] = useState(false)
return (
<Router>
<Routes>
{ isLogin ? <Topbar />
<div className="container">
<Sidebar />
<Route path="/" element={<Home />} />
<Route path="users" element={<UserList />} />
</div> : <Route path="login" element={<Login />} />
</Routes>
</Router>
);
};

how to get params using react router dom v5.0.1

how to get params using react router dom v5.0.1 before I could get parameters, but now I can't get them, what's the problem?
<BrowserRouter>
<Route path='/' exact component={Login} />
<Route path='/register' component={Register} />
<Route path='/home' component={Home} />
<Route path='/all/merchant' component={AllMerchant} />
<Route path='/detail/merchant/:id_merchant' exact component={DetailMerchant} />
<Route path='/detail/merchant/promo/:id_merchant' component={MerchantByPromo} />
<Route path='/promo/voucher/by/merchant/' component={MerchantByPromoDetail} />
<Route path='/all/category' component={Category} />
<Route path='/category/id/:category_id' component={CategoryById} render = {props => <CategoryById {...props} key={this.props.match.params} /> }/>
<Route path='/promo/grid/view' component={PromoGridView} />
{/* params not found */}
<Route path='/promo/grid/view/by/category/:category_id' component={AllPromoGridView} />
<Route path='/detail/promo/:voucher_id/category_id/:category_id' component={PromoGridViewDetail} />
{/* params not found */}
<Route path='/account' component={Account} />
</BrowserRouter>
According to the react-router doc, it should be accessible in your Component via the props match:
Example:
// the route
<Route path="/:id" component={Child} />
/*
...
*/
//the component
function Child({ match }) {
return (
<div>
<h3>ID: {match.params.id}</h3>
</div>
);
}

Meteor/React Router 4 - Homepage and connected user

Another post to ask you about a "situation" I am having, which is disappointing as my Router is creating too many refreshs and for the point is actually not to have to refresh part of the page by using React.
I would like the following :
When I go to './' and there is no user connected it shows a homepage (without header and footer)
When I go to './' and I am connected or any other link whether I am connected ot not it should show the relevant page with a Header and a Footer.
So the fact of being not connected does not show header/footer is only true for the './' address.
How I solved it and it is not satisfying because it seems my header is rerendering all the time I change pages even between two pages with Router....
I have a first Router, the AppRouter :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
<SubRouter />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
My index is like that :
export class Index extends React.Component {
render() {
if (this.props.user){
return (
<SubRouter />
)
} else {
return (
<Homepage />
)
}
}
}
So if no user the Homepage is showing if user it goes back to the SubRouter.
SubRouter is like that :
export class SubRouter extends React.Component {
(...)
render(){
return (
<div className="fullpage">
{this.state.inboxOpen ? <Inbox closeInbox={this.closeInbox} oneUserInboxId={this.state.oneUserInboxId} /> : undefined }
<Header openInbox={this.openInbox} closeInbox={this.closeInbox} />
<Switch>
<Route path="/" component={Dashboard} exact={true} />
<Route path="/admin" component={Admin} exact={true} />
<Route path="/account" component={Account} exact={true} />
<Route path="/settings" component={Settings} exact={true} />
<Route path="/faq" component={Faq} exact={true} />
<Route path="/cgv" component={Cgv} exact={true}/>
<Route path="/legal" component={Legal} exact={true}/>
<Route path="/login" component={Login} exact={true}/>
<Route path="/signup" component={Signup} exact={true}/>
<Route path="/notifications" render={() => (<Dashboard notifications={true} />)} exact={true} />
}} />
<Route path="/reset-password/:token" component={ResetPassword} />
<Route path="/forgot_password" component={ForgotPassword} exact={true} />
<Route path="/post/:postId" component={OnePost} />
<Route path="/*" component={NotFound} />
</Switch>
<Footer />
</div>
)
}
}
So this code is "working" but somehow we can see rerenders that should not happen, I am open to any idea to optimize this. Thanks in advance !
Problem was coming from here :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
<SubRouter />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;
Should not have rerendered SubRouter here as it is already rendered in HomePage. Good code is :
const AppRouter = () => (
<BrowserRouter>
<div className="content">
<Switch>
<Route path="/" component={Index} exact={true} />
</Switch>
</div>
</BrowserRouter>
);
export default AppRouter;

Attempting to pass a custom attribute into react router (using v4)

I have the following render method in my App.js:
render() {
return (
<LocaleProvider locale={enUS}>
<Router history={history}>
<div>
<Header />
<Switch>
<Route exact path={home} component={requireAuth(Groups)} />
<Route exact path={groups} component={requireAuth(Groups)} />
<Route path={addcard} component={requireAuth(AddCard)} />
<Route path={db} component={requireAuth(DbTbl)} />
<Route component={NoMatch} />
</Switch>
</div>
</Router>
</LocaleProvider>
);
};
And I want to pass in a custom property to the first 2 routes ({home} & {groups}) so I'm attempting to do something like this:
render() {
const groups1 = () => <Groups studyState={this.toggleStudyState}/>;
return (
<LocaleProvider locale={enUS}>
<Router history={history}>
<div>
<Header />
<Switch>
<Route exact path={home} render={requireAuth(groups1)} />
<Route exact path={groups} render={requireAuth(groups1)} />
<Route path={addcard} component={requireAuth(AddCard)} />
<Route path={db} component={requireAuth(DbTbl)} />
<Route component={NoMatch} />
</Switch>
</div>
</Router>
</LocaleProvider>
);
};
But I'm getting this error message from react router:
connectAdvanced.js:3 Uncaught TypeError: Cannot call a class as a
function
So I suspect react router doesn't like the high order component syntax with the render= attribute. How can I pass the studyState attribute into the Groups component being used with the first two tags?
The render property must have a function passed to it. You are giving a Class.
Write something like that:
<Route exact path={home} render={(routerProps) => {
const AuthGroups = requireAuth(Groups);
return <AuthGroups studyState={this.toggleStudyState}/>;
}} />
As I don't know how the requireAuth works, I don't know if the studyState property will be properly passed to the Group component. But I guess it will.
Now to have a cleaner code (if the above solution works):
renderAuthGroups(routerProps) {
const AuthGroups = requireAuth(Groups);
return <AuthGroups studyState={this.toggleStudyState}/>;
}
render() {
return (
<LocaleProvider locale={enUS}>
<Router history={history}>
<div>
<Header />
<Switch>
<Route exact path={home} render={this.renderAuthGroups.bind(this)} />
<Route exact path={groups} render={this.renderAuthGroups.bind(this)} />
<Route path={addcard} component={requireAuth(AddCard)} />
<Route path={db} component={requireAuth(DbTbl)} />
<Route component={NoMatch} />
</Switch>
</div>
</Router>
</LocaleProvider>
);
};

Categories