I am relatively new to react and attempting to create an app that has 2 designs. One is the public site that has a common header and footer and the internal app which has an admin header and side bar. I created a Router and 2 main routes '/' and '/app'. I then added subroutes hoping that if the parent routers were matched, it would show the parent component and pass the sub route's component as the this.props.children. I seemed to have done it wrong. Here is what I created.
App.js:
...
class App extends Component {
render() {
return (
<Router>
<Switch>
<Route component={Public}>
<Route exact path="/" component={Home}/>
<Route path="/login" component={Login}/>
</Route>
<Route component={Main}>
<Route path="/dash" component={Dash}/>
<Route path="/people" component={People}/>
</Route>
</Switch>
</Router>
);
}
}
...
Public 'template':
...
render(){
return(
<div>
I am a public page
{this.props.children}
</div>
)
}
...
Home.js
...
class Home extends Component{
render(){
return(
<div>I am the home page</div>
)
}
}
...
App 'template'
...
class Main extends Component{
render(){
return(
<div>
<Header />
<div>I am an app page</div>
{this.props.children}
<Footer/>
</div>
)
}
}
...
Dash.js
...
class Dash extends Component{
render(){
return(
<div>I am the dash page</div>
)
}
}
...
Thanks and if any one can tell me or point me to a good resource I would appreciate it!
You're really close! What you need to do is actually put the template components as the parent not in a <Route /> component. A components children are the components in between its start and end tag. Keep on trucking !
class App extends Component {
render() {
return (
<Router>
<Switch>
<Public>
<Route exact path="/" component={Home}/>
<Route path="/login" component={Login}/>
</Public >
<Main>
<Route path="/dash" component={Dash}/>
<Route path="/people" component={People}/>
</Main>
</Switch>
</Router>
);
}
}
Related
(I'm using React - Class Component)
I'm looking for how to remove Footer component only in specific page, but i have no idea. Actually I don't have no idea about what keyword to search.
Below code is my Router.js
class Routes extends React.Component {
render() {
return (
<Router>
<Navbar />
<Switch>
<Route exact path="/" component={Main}></Route>
<Route exact path="/review" component={ReviewPage}></Route>
</Switch>
<Footer />
</Router>
);
}
}
export default Routes;
I put Footer and Navbar Component in router like that because those are always exists in every page. But unfortunately I just found that in ReviewPage, there is NO FOOTER....
How can i remove Footer only in ReviewPage?
Please give me hint !
You can use location.pathname. It returns the current url path name. And then you can set a condition as below:
{location.pathname !== '/review' && <Footer />}
Solution
class Routes extends React.Component {
render() {
return (
<Router>
<Navbar />
<Switch>
<Route exact path="/" component={Main}></Route>
<Route exact path="/review" component={ReviewPage}></Route>
</Switch>
{location.pathname !== '/review' && <Footer /> }
</Router>
);
}
}
export default Routes;
{Location.pathname === '/photographer/:id' && }
and you can see new version React-router
Now use Location != location and it works
<>
<Header />
<main>
<Container>
<Routes>
<Route path='/' element={<HomeScreen />}></Route>
<Route
path='/photographer/:id'
element={<PhotographersScreen/>}
></Route>
</Routes>
</Container>
</main>
{Location.pathname === '/photographer/:id' && <Footer />}
</>
My Setup:
routes.js
const Router = () => (
<Switch>
<Route path="/" component={ Dashboard } />
<Route path="/somepath" component={ SomePath } />
</Switch>
);
index.js
<HashRouter>
<App />
</HashRouter>
app.js:
lass App extends Component {
render() {
return (
<div className="main-app">
<Header />
<div className="page__container">
<Router />
</div>
<Footer />
</div>
);
}
}
Issue is, when I navigate to localhost/#/ rootpath, it is correctly rendering Dashboard component as mentioned in routes.js file. But When I naviagte to localhost/#/somepath, it not rendering component for somepath, it is stil rendering / Component.
Even in React Devtool it shows <Route path="/"> is loaded, not <Route path="/somepath">
You may have to add exact to match the path. add exact prop to Route
<Route exact path="/somepath" component={ SomePath } />
I want to use layouts with my react-router-dom, at this moment i am doing that like this
const DefaultLayout = ({children, ...rest}) => {
return (
<div className={styles.wrapper}>
<Header/>
{children}
<Footer/>
</div>
)
};
const DefaultRoute = ({component: Component, ...rest}) => {
return (
<Route {...rest} render={matchProps => (
<DefaultLayout>
<Component {...matchProps} />
</DefaultLayout>
)}/>
)
};
render(
<Provider store={store}>
<HashRouter>
<Switch>
<DefaultRoute exact path="/" component={AdvertList}/>
<DefaultRoute exact path="/user" component={UserOptions}/>
<Route path="/login" children={Login}/>
<Route render={
() => (
<div>
Not found
</div>
)
}/>
</Switch>
</HashRouter>
</Provider>,
document.querySelector('#app')
);
it works okay, both UserOptions and AdvertList components are rendered inside DefaultLayout, and Login component does not, but in official documentation i didn't find solution like that, instead there is "nested routing" where you adding new nested routes in subclasses, like
if you need default layout u make it on route /, then if you need advert list with that layout, in layout component you defined route /adverts and adding link to it, and so on, each sub component uses layout of parent one.
But in my case there is already product list on route /, and i need to change that content to other products list regarding link pressed, not to add to parent layout, but to change it part. Here is my code,
const { BrowserRouter, Route, Switch, Link } = window.ReactRouterDOM;
const { Component } = window.React;
const About = () => ('About');
const MiscProducts = () => ('Misc products');
class AdvertsList extends Component {
render() {
return (
<div className="container">
<header>Header</header>
<main>
<nav>
<Link to="/miscProducts">Misc Products</Link> #
<Link to="/about">About</Link>
</nav>
<div className="content">
Main Products
</div>
</main>
<footer>Footer</footer>
<Route path="/miscProducts" component={MiscProducts} />
</div>
)
};
};
class App extends Component {
render() {
return (
<BrowserRouter>
<Switch>
<Route path="/" component={AdvertsList} />
<Route path="/about" component={About} />
<Route path="*" render={
() => (
<div>
Not found
</div>
)
}/>
</Switch>
</BrowserRouter>
);
}
}
ReactDOM.render(<App />, document.querySelector("#app"));
http://jsfiddle.net/gmcke2a4/6/ here main products loaded by default, and when i press misc products, misc products must be loaded instead of main one.
p.s. And why about doesn't work?
Login Fix
<Route path="/login" children={Login}/> this seems wrong because children component expects function which return nodes i think.Try <Route path="/login" children={() => (</Login />)}
Layout
But in my case there is already product list on route /, and i need to
change that content to other products list regarding link pressed, not
to add to parent layout
You can create component which renders specific products like this.
const MainProducts = () => 'Main Products'
const GummyBearsProducts = () => 'GummyBears'
const Products = props => (
<div className="products-container">
<Switch>
<Route path={`${props.location.pathname}`} component={MainProducts}/>
<Route path={`${props.location.pathname}/gummy-bears`} components={GummyBearProducts}/>
</Switch>
</div>
)
And then use it as follows.
class AdvertsList extends Component {
render() {
return (
<div className="container">
<header>Header</header>
<main>
<nav>
<Link to="/products">Products</Link> #
<Link to="/about">About</Link>
</nav>
<div className="content">
<Route path="/products" component={Products} />
</div>
</main>
<footer>Footer</footer>
</div>
)
};
};
React router is great in rendering specific components.I hope it answers your question.Cheers!
If you are using react-router-dom v6. Then follow the below procedure to configure react-router-dom,
App.jsx:
import './App.css';
import { BrowserRouter, Routes, Route } from 'react-router-dom'
import Home from './Components/Home'
import About from './Components/About'
import Layout from './Components/Layout'
function App() {
return (
<div className="App">
<BrowserRouter>
<Routes>
<Route path="/" element={<Layout />}>
<Route path="/" element={<Home />} />
<Route path="about" element={<About />} />
</Route>
</Routes>
</BrowserRouter>
</div>
);
}
export default App;
After configuring the react router in App.jsx. I am creating 3 components Home, About and Layout. Home and About are regular components and Layout component is to handle the Layout part in react-router-dom using Outlet.
Layout.jsx
import { Outlet, Link } from 'react-router-dom'
export default function Layout() {
return (
<>
<Link to="/">Home</Link>
<Link to="/about">About</Link>
<Outlet />
</>
)
}
Home.jsx
export default function Home() {
return (
<>
<p>This is Home</p>
</>
)
}
About.jsx
export default function About() {
return (
<>
<p>This is About Us</p>
</>
)
}
I have a component like this
class myApp extends React.Component {
return (
<div>
<NavigationBar />
{/* dynamic_content */}
</div> )
}
with this route
<Router>
<Route exact path="/" component={myApp}/>
</Router>
And it loads fine.
What I'd like to achieve is that when the url changes, for example
/profile
/notifications
the dynamic_content is updated, without actually transitioning to another component.
In pseudocode what I want is like
class myApp extends React.Component {
return (
<div>
<NavigationBar />
{route === '/profile' -> <Profile/>
route === '/notification' -> <Notification/>}
</div> )
is this even possible?
How can I do that?
Yes, it is possible, what you need is to define nested Routes like
class MyApp extends React.Component {
return (
<div>
<NavigationBar />
{/* dynamic_content */}
<Route path='/profile' component={Profile}/>
<Route path="/notification" component={Notification}/>
</div> )
}
and configure your Parent route without a exact props
<Router>
<Route path="/" component={MyApp}/>
</Router>
Also you must define your components with UpperCase character as the first letter
my / route doesn't properly render my main component.
Her is my code:
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" componenet={Main}>
<IndexRoute component={Index}></IndexRoute>
<Route path="portfolio" component={Portfolio}></Route>
</Route>
</Router>,
document.getElementById('app')
);
This is my Main component:
export default class Main extends React.Component {
render() {
console.log("asdfasfsaf");
return(
<div>
<h1> This is Main Page </h1>
{this.props.children}
</div>
)
}
}
Once i load the website it doesn't console log anything nor render <h1> This is main page header. Also If I delete this Main componenet it still goes to my IndexRoute without any error which is my index componenet.
Try this:
ReactDOM.render((
<Router history={browserHistory}>
<Route path="/" componenet={Main}>
<IndexRoute component={Index}></IndexRoute>
<Route path="portfolio" component={Portfolio}></Route>
</Route>
</Router>,
), document.getElementById('app'));