ReactJS - Change Component in parent depending on nested route - reactjs

I have my App wrapped in a component which renders a Header, Footer and any routed child components.
I am trying to replace the <Header /> component with </HeaderAdmin/> when at /admin.
Routes
<Route path='/' component={SiteWrapper} >
<IndexRoute component={Home} />
<Route path="admin" component={Admin}>
<Route path="dashboard" component={Dashboard}/>
</Route>
</Route>
SiteWrapper Comp
export default class SiteWrapper extends React.Component {
render() {
return (
<div>
<Header/> // Want to replace with <AdminHeader /> if on /admin
<div className="container">
{this.props.children.props.route.header ? <PageHeader header={this.props.children.props.route.header} /> : null}
{this.props.children}
</div>
<Footer/>
</div>
)
}
}

You can use this.props.location.pathname to find the route name
export default class SiteWrapper extends React.Component {
render() {
return (
<div>
{(this.prop.location.pathname === 'admin')? <AdminHeader/>: <Header/>}
<div className="container">
{this.props.children.props.route.header ? <PageHeader header={this.props.children.props.route.header} /> : null}
{this.props.children}
</div>
<Footer/>
</div>
)
}
}

For that, I think you can check the route by window.location or this.props.location.pathname, it will contain the route names, if the route name is /admin then render the Header component otherwise render the AdminHeader component.
Write it like this:
{ this.prop.location.pathname === '/admin'? <AdminHeader/>: <Header/>}

Related

When routing , component is not rendering in Side page

This the js file where I have added my router and it contains all the route of my application
router. Below is the code of My App.js
export default class App extends Component {
static displayName = App.name;
render() {
return (
<Router>
<Layout />
<Switch>
<Route path='/employee' exact component={Employee} />
<Route path='/employer' component={Employer} />
<Route path='/addEmployer' component={AddEmployer} />
<Route path='/user' component={UserManagement} />
<Route path='/addUser' component={AddUser} />
</Switch>
</Router>
);
}
}
I have created the Layout page which contains my navbar component, sidebar component, main content and footer too.
Below is the code of Layout.js. I want my layout to be static across the application
import React, { Component } from 'react';
import { Container } from 'reactstrap';
import '../../css/main.css';
import { Navbar } from './Navbar';
import { Footer } from './Footer';
import { SideNavbar } from './SideNavbar';
export class Layout extends Component {
static displayName = Layout.name;
constructor(props) {
super(props);
}
render() {
return (
<div>
<Navbar />
<div id="layoutSidenav">
<SideNavbar />
<div id="layoutSidenav_content">
<main className="flex">
{this.props.children}
</main>
<Footer />
</div>
</div>
</div>
);
}
}
When I am routing the employer from url, the employer component is not rendering under main folder.
currently it is been rendering under the footer of the page. This causing an issue in makin my application as SPA.
Awaiting the response
Issue
Your Layout component looks to be designed to render the content as children, but in your App component you don't pass it any children. The Switch is rendered under/after Layout component.
class Layout extends Component {
static displayName = Layout.name;
constructor(props) {
super(props);
}
render() {
return (
<div>
<Navbar />
<div id="layoutSidenav">
<SideNavbar />
<div id="layoutSidenav_content">
<main className="flex">
{this.props.children} // <-- content
</main>
<Footer />
</div>
</div>
</div>
);
}
}
class App extends Component {
static displayName = App.name;
render() {
return (
<Router>
<Layout /> // <-- no children
<Switch>
<Route path='/employee' exact component={Employee} />
<Route path='/employer' component={Employer} />
<Route path='/addEmployer' component={AddEmployer} />
<Route path='/user' component={UserManagement} />
<Route path='/addUser' component={AddUser} />
</Switch>
</Router>
);
}
}
Solution
Wrap the Switch.
class App extends Component {
static displayName = App.name;
render() {
return (
<Router>
<Layout>
<Switch>
<Route path='/employee' exact component={Employee} />
<Route path='/employer' component={Employer} />
<Route path='/addEmployer' component={AddEmployer} />
<Route path='/user' component={UserManagement} />
<Route path='/addUser' component={AddUser} />
</Switch>
</Layout>
</Router>
);
}
}
Router needs to define where we wanted to render our component. Like In my case it should be under Layout component itself rather the defining at App.js part

route is not loading component inside nested route component

I'm loading my adminDashboard component in app.js with Route. now in adminDashboard based on URL, I want to render some component. but, it's not loading any component. also, there is no activity on the network tab in chrome console.
if I render them without Route, they are rendering properly.
app.js
class App extends Component {
render() {
let { error, success } = this.props;
const Admin = Authorization(['admin'])
return (
<div className='app'>
<AdminNavbar logout={this.props.logout}/>
<Switch>
<Route exact path='/admin/signin' render={(props) => {
return <AuthForm />
}}
/>
<Route exact path='/admin' component={Admin(AdminDashboard)} />
</Switch>
<Footer />
</div>
);
}
}
MyComponent component
const MyDashboard = (props)=> ` this is dashboard`
Admindashboard
class AdminDashboard extends Component{
render() {
return (
<div>
<div className='row'>
<div className='col-md-2'>
<NavBar />
</div>
<div className='col-md-10'>
< Commisions /> //working properly if i load it without route
<Switch>
<Route exact path='/admin/dashboard' component={MyDashboard} /> // not work
//some other route
</Switch>
</div>
</div>
</div>
)
}
}

How to implement nested Routing (child routes) in react router v4?

The component tree i want is as below
- Login
- Home
- Contact
- About
Contact and About are children of Home.
This is my App.js ,
class App extends Component {
render() {
return (
<BrowserRouter>
<div>
<Route exact path="/home" component={HomeView} />
</div>
</BrowserRouter>
);
}
}
render(<App />, document.getElementById('root'));
This is Home,
export const HomeView = ({match}) => {
return(
<div>
<NavBar />
Here i want to render the contact component, (Navbar need to stay)
</div>
)
}
This is my Navbar,
export const NavBar = () => {
return (
<div>
<Link to="/home">Home</Link>
<Link to="/home/contact">Contact</Link>
<hr/>
</div>
)
}
Contact component just need to render "hello text".
To make nested routes you need to remove exact:
<Route path="/home" component={HomeRouter} />
And add some routes:
export const HomeRouter = ({match}) => {
return(
<div>
<NavBar />
{/* match.path should be equal to '/home' */}
<Switch>
<Route exact path={match.path} component={HomeView} />
<Route exact path={match.path + '/contact'} component={HomeContact} />
<Switch>
</div>
)
}
You don't need use match.path in nested routes but this way it will be easier to move everything from "/home" to "/new/home" in case you decide to change your routing.

React router v4 - route with params renders blank page?

I'm trying to implement React Router v4 in my create-react-app app and my routes work except for the route with an /:id parameter as it just renders a blank page. I've searched for 2 days and tried implementing the solutions here which says to add <base href="/" /> to the head section of index.html and I've also tried following this Medium guide for simple routing but it still does not work. I don't understand, what is going on?
My code is below, any help is greatly appreciated!
Index.js
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>),
document.getElementById('root'));
registerServiceWorker();
App.js
class App extends Component {
render() {
return (
<Routes />
)
}
}
Routes.js
export const Routes = () => {
return (
<main>
<Switch>
<Route exact path="/" component={Home} />
<Route exact path="/movies" component={Search} />
</Switch>
</main>
);
}
Search.js
render() {
let filteredMovies = this.state.movies.filter((movie) => {
return movie.title.toLowerCase().indexOf(this.state.search.toLowerCase()) !== -1;
})
return (
<div>
<p>Search Page</p>
<form>
<input type="text" value={this.state.search} onChange={this.updateSearch}/>
</form>
<div>
{filteredMovies.map((movie, idx) =>
<div>
<div key={idx}>
<Link to={`/movies/${movie.videoId}`}>
<img src={movie.image.high.url} height="160px" width="100px" alt=""/>
<p>{movie.title}</p>
<p>{movie.quality}</p>
</Link>
</div>
</div>
)}
</div>
<Switch>
<Route path="/movies/:id" component={Single} />
</Switch>
</div>
)
}
}
export default Search;
Single.js
class Single extends Component {
render() {
return (
<div>
<p>Single Movie...</p>
{this.props.match.params.id}
</div>
)
}
}
export default withRouter(Single);
Every route works except for /movies/:id where it just renders a completely blank page. It doesn't even show the <p>Single Movie...</p>.
You should remove exact from route that corresponds to Search component in your Routes, i. e.:
export const Routes = () => {
return (
<main>
<Switch>
<Route exact path="/" component={Home} />
<Route path="/movies" component={Search} />
</Switch>
</main>
);
}
The explanation is pretty simple: the exact prop means that your component will render only if current route is exactly the same as you specified in the path prop
Update
If you want to render the list of movies only when no :id is specified, you should render your list in Switch:
<Switch>
<Route exact path="/movies" render={props => {
return (
<div>
{filteredMovies.map((movie, idx) =>
<div>
<div key={idx}>
<Link to={`/movies/${movie.videoId}`}>
<img src={movie.image.high.url} height="160px" width="100px" alt=""/>
<p>{movie.title}</p>
<p>{movie.quality}</p>
</Link>
</div>
</div>
)}
</div>
)
} />
<Route path="/movies/:id" component={Single} />
</Switch>

Can't render children (let alone routed children) inside routed react component

Building my first React app and I am trying to create a nested router within the authenticated 'internal' page but it's proving quite difficult. I've tried a number of things, but this is the latest incarnation--and I am getting a cannot read 'children' property of undefined error in the AuthenticatedFrame component.
export class NavigationFrame extends React.Component<INavigationFrameProps, {}> {
render() {
console.log(this.props)
console.log(this.state)
console.log(this.props.store.store.getState())
return <Router>
<div className="navigation-frame">
<Route exact path="/" component={Splash}/>
<Route exact path="/register" component={RegistrationForm}/>
<Route path="/signin" component={SignInContainer}/>
<Route path="/i" render={() => (
this.props.store.store.getState().authenticationState.authenticated ? (
<AuthenticatedFrame>
<Route exact path="/i/" component={WelcomePage}/>
<Route path="/i/add" component={AddPage}/>
</AuthenticatedFrame>
) : (
<Redirect to="/signin"/>
)
)}/>
</div>
</Router>;
}
}
And my AuthenticatedFrame (doesn't work)
export const AuthenticatedFrame = () => (
<div className="internal-view">
<SidebarDrawer />
<div className="content-area">
{this.props.children}
</div>
</div>)
AuthenticatedFrame is a functional component and hence doesn't have access to this keyword, you need to access props as function arguments like
export const AuthenticatedFrame = (props) => (
<div className="internal-view">
<SidebarDrawer />
<div className="content-area">
{props.children}
</div>
</div>
)
Urf. I just had to change out Authenticated Frame with this:
export class AuthenticatedFrame extends React.Component<{children: any}, {}> {
render() { return <div className="internal-view">
<SidebarDrawer />
<div className="content-area">
{this.props.children}
</div>
</div>}

Resources