SamYoungNY
SamYoungNY

Reputation: 6624

Hide App Elements React

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

Answers (2)

intentionally-left-nil
intentionally-left-nil

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

Ishan Trivid
Ishan Trivid

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

Related Questions