Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application Layout? #71

Closed
davidrossjones opened this issue Oct 25, 2016 · 10 comments
Closed

Application Layout? #71

davidrossjones opened this issue Oct 25, 2016 · 10 comments

Comments

@davidrossjones
Copy link
Contributor

In the React context, when building an app I'm used to the concept of containers and components. It appears to me that "pages" are somewhat equivalent to containers within next.js.

Is there a recommended way to add an application layout container such that I could specify for example global <Header/> and <Footer/> components with the router determining which content to display within (the page)? Similar to how the popular react-router package match function can be configured on the server.

Using the next.js default router and pages folder as is, to achieve this do I have no option but to duplicate <Header/> and <Footer/> across all pages?

@altaywtf
Copy link

altaywtf commented Oct 25, 2016

Just an idea: you may consider to write an higher order component that takes your page component and returns some structure like this

<section>
   <Header />
   <YourPageComponent />
   <Footer />
</section>

Update:

components/AppLayout.js

import React, { Component } from 'react';
import { Header, Footer } from 'components';

const withAppLayout = () => (ComposedComponent) => {
  class AppLayout extends Component {
    render() {
      return (
        <section>
           <Header />
           <ComposedComponent {...this.props} />
           <Footer />
         </section>
      );
    }
  }

  return AppLayout;
};

export default withAppLayout;

pages/index.js

import withAppLayout from 'components/AppLayout';

const Home = () => (<div>Home</div>);

export default withAppLayout(Home);

@davidrossjones
Copy link
Contributor Author

Thank you for your reply 😃 .

Where would I specify this HOC in the context of next.js though?

The default router will render index.js for / and about.js for /about. Do I have to duplicate for both?

index.js

export default () => (
  <div><Header/>Home<Footer/></div>
)

about.js

export default () => (
  <div><Header/>About<Footer/></div>
)

@impronunciable
Copy link
Contributor

@davidrossjones one option is:

// components/Layout.js

export default () => (
  <div>
    <h1>Header</h1>
    {this.props.children}
    <footer>the footer</footer>
  </div>
)
// pages/index.js

import Layout from '../components/Layout'

export default () => (
  <Layout>
    <p>Home</p>
  </Layout>
)
// pages/about.js

import Layout from '../components/Layout'

export default () => (
  <Layout>
    <p>About</p>
  </Layout>
)

@davidrossjones
Copy link
Contributor Author

Aha! That makes perfect sense.

Thank you @altayaydemir and @impronunciable for the insight! Awesome. 👍

@dlindenkreuz
Copy link
Contributor

@impronunciable @altayaydemir Apparently, the Layout wrapper component gets re-mounted when changing routes which does not completely solve the problem. @ericf describes this in #50.

@altaywtf
Copy link

@dlindenkreuz well, you are right. 😥 I also agree on having an app layout component.

@cupliz
Copy link

cupliz commented May 27, 2017

how to get initial props using this layout? like this

static getInitialProps ({ req}) {
  return {request: req ? 'Server' : 'Client '}
}

@mpint
Copy link

mpint commented May 7, 2018

In the React context, when building an app I'm used to the concept of containers and components. It appears to me that "pages" are somewhat equivalent to containers within next.js.

I was wondering the same thing as well. Is there anything fundamentally different between pages and containers?

@Katyadelarosa
Copy link

Wondering the same over here.

I was used more to.

./pages/Index.js

const IndexPage = ({ serverCall }) => (
 <div>
   <button onClick={serverCall}>Hello</button>
</div>
);

export default IndexPage;

And then on.

 ./containers/Index.is

import IndexPage from './pages/Index.js'

const composerData = (props, onData) => {
   onData(null, {
     serverCall: () => console.log('call');
   })
};
export default compose(composerData)(IndexPage);

where compose can be something like https://github.com/arunoda/react-komposer, but still i'm not sure if this the correct usage for NextJs, or i can avoid the Container and do this on the Page directly

@timneutkens
Copy link
Member

You could use pages/_app.js for global layout now.

ijjk pushed a commit to ijjk/next.js that referenced this issue Apr 13, 2019
@lock lock bot locked as resolved and limited conversation to collaborators Sep 7, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants