Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to divide my app into reusable components using server side rendering in Next.js [closed]

I am confused about writing a Next.js application which will render the pages server-side when I have reusable components and <Link>s to navigate to other areas of the application.

The documentation says

  • getInitialProps (SSR) is only called for pages, and not called for components"
  • componentWillMount is not executed server side, its client-side rendering only
  • <Link> tag is only client side navigation therefore "pages" it navigates to are rendered client side

My questions

I am unclear on the following:

  1. How to break up your application into reusable components keeping server-side rendering?
  2. If there are <Link>s to other pages of the application, how can the other pages be rendered on the server?
  3. If <Link>s are client side, surely this means only the initial page will be rendered server-side, so what is the point of writing an app in Nextjs rather than plain React?
  4. If getInitialProps is only called for pages, surely this means that the page's getInitialProps has to do all the server calls for any data rendered on its page and then send to child components, and this must be very slow. If a page contains a list of items, there is going to be one server call to get the list of items, and for each item in the list there will need to be a call to get the items details and another call to get the items image. This is a lot of server calls before the page is rendered.

My application

I thought it would be easier to illustrate my issue with a sample application of the sort of things I want to be able to do.

  • My application has several pages: Tab-1, Tab-2, Tab-3, Tab-4 and details pages for items listed in Tab-1 and Tab-2 etc.
  • Each page in my application has the same layout, a header area, a tab bar, the page's content and a footer
  • On clicking items in the tab bar you can navigate to the other pages in my application
  • Each tab contains a list of items of different categories, clicking on an item in the lists takes the user to the details "page" for that item

Here is a graphical representation of my application.

application graphical representation

Project structure

All pages use layout-template to add the main structure of header and footer and then adds its own content in the middle of the page using components

|- pages
     |- index.js  (i.e. tab-1)
     |- tab2.js
     |- tab3.js
     |- tab4.js
     |- aitem
          |- [id].js
     |- numitem
          |- [id].js
|- Components
     |- layout-template.js --- needs data to pass to header/footer
     |- header.js
     |- footer.js
     |- AlphabetList --- needs data
     |- AlphabetListItem --- needs data

Below are samples of my components showing how they make up my application. See in some of the components they have to get data from the server.

As they are components they are getting their data in componentWillMount, which means that component will not render server-side. Therefore this seems to completely defeat the purpose of writing Next.js.

Component = layout_template.js needs to get data from the server to pass to header and footer

layout template image

Component = header.js just contains JSX

header

Page = Index.js (URL= "/" or "/index") doesn’t get any data from the server, just specifies JSX

index page

Component = AlphabetList.js gets the list of alphabet items from the server and renders it using another component

alphabet items

Component = AlphabetListItem.js gets the item's image from the server then renders it. On clicking on this component the app goes to the item's details page

gets alphabet item's image

Page = AlphabetItemDetails.js ( URL = "aitem/[id]") gets additional information about the item from the server and renders fill details of the item

gets additional information

How do I structure my code?

  • For the main layout/header/footer to render server-side, do I have to duplicate the code to get the logo in the getInitialProps in every page? i.e. in index.js, tab2.js, tab3.js, tab4.js, aitem/[id].js and numitem/[id].js? This seems to go against any decent code design of not duplicating code and instead pull into reusable code.
  • For all the data in a page to be rendered server-side, do I have to get all the list items and then get each items details and image URL in the getInitialProps of the page?
like image 446
se22as Avatar asked Feb 24 '20 15:02

se22as


1 Answers

First of all tabs need not be a new page. Tabs can be components.

On the main page (index.js), you can transfer the data you get using getInitialProps to components with prop.

You can also send data to components such as header and footer via prop via Layout. For the logo in the header, instead of pulling data again on each page, you can create _app.js to the pages folder and pull data from here with getInitialProps.

For more detailed information, you can visit this page https://nextjs.org/docs/getting-started

like image 155
Osman Safak Avatar answered Oct 01 '22 16:10

Osman Safak