Reputation: 6624
I have an <App/>
component which renders for any page on my site:
const App = () => (
<div>
<Header />
<Main />
<Footer />
<Subfooter />
<SubfooterLegal />
</div>
)
export default App;
The problem I'm having now is that I have a Component (page) which doesn't include any of the components within <App />
aside from <Main />
(which is the router).
I'm puzzled on how to do this, since App.js
is the parent component of all components. My only idea of how to do this (possibly) is that when a user clicks a <Link />
to the aforementioned component, I could add setState
(maybe?) to App.js
and change it to something like hideAppComponents = true
and then hide the appropriate components. I know that in this case I would have to make <App />
extends Component
since it would then be stateful.
Are there any suggested approaches for a use case like this?
Upvotes: 0
Views: 88
Reputation: 8274
As far as answering your specific question: Yes, adding state to your App
and then rendering differently depending on the page would work.
However, a small refactoring of your components would make your problem easier.
In my opinion, a good use of <app>
within the context of routing is to just use it to reference which route the user will be on.
<app>
<main>
<Switch>
<Route exact path='/' component={Home}/>
<Route exact path='/about' component={AboutUs}/>
<Route path='/somePageWithoutAFooter' component={CoolPage}/>
</Switch>
</main>
</app>
Now, you have set just a very set of minimal constraints from your top-level app. Depending on the route, you will render a specific child component. So this solves your direct problem. Now you can have CoolPage
be its own custom thing, but then the Home
page can do something else.
So far, so good. However lets say that both Home
and AboutUs
have the same basic template of the header and the subfooter that you've been talking about. It would be unfortunate for both of these components to have to describe this architecture inside the render. Instead, you could make a container component like this:
class MyLayout extends Component {
render() {
<div>
<Header />
{this.props.children}
<Footer />
<Subfooter />
<SubfooterLegal />
</div>
}
}
And this component can be used like this:
<MyLayout><Home></MyLayout>
So now, all you need to do is to wrap all of your normal pages in a MyLayout
. This can either be done in the app
itself, or in a child if it gets more complicated.
Edit: This example uses react-router
since this post was tagged with it. You can follow the same principles without using the router if you want. It just makes the <Route>
stuff easier to manage.
Upvotes: 1
Reputation: 101
the only possible solution i can think other than your solution is to use loaction prop. Below is the sample code you can try.
import STORE from './store/STORE';
import {Provider} from 'react-redux';
import {Route, Router} from 'react-router-dom';
import createHashHistory from 'history/createHashHistory';
const history = createHashHistory();
render(
<Provider store={STORE}>
<Router history={history}>
<Route path="/" component={App}/>
</Router>
</Provider>, document.getElementById('app')
);
const App = (location) => (
location.pathname.includes("error") ?
<div>
<Main />
</div> :
<div>
<Header />
<Main />
<Footer />
<Subfooter />
<SubfooterLegal />
</div>
)
export default App;
Upvotes: 0