Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NextJS Track Mounted Components in SSR

The following applies to SSR via NextJS.

I'm using React's context to keep track of IDs of certain mounted components. The gist is

class Root extends React.Component {
  getChildContext () {
    return {
      registerComponent: this.registerComponent
    }
  }

  registerComponent = (id) => {
    this.setState(({ mountedComponents }) => {
      return { mountedComponents: [...mountedComponents, id ] }
    })
  }

  ...
}

class ChildComponent {
  static contextTypes = { registerComponent: PropTypes.func }

  constructor(props) {
    super(props)

    props.registerComponent(props.id)
  }
}

unfortunately this only works client-side. this.state.mountedComponents is always [] on the server. Is there another way to track these components server-side? Basically I need the ids to provide to a script to run in the head of the document - waiting until the client app mounts, runs, and appends to the head manually is a little too slow.

update

here's a quick example repo: https://github.com/tills13/nextjs-ssr-context

this.context is undefined in the constructor of Child, if I move it to componentDidMount (currently set up this way in the repo), it works, but I'd like this to be resolved server-side. I'm not dead-set on context, if there's another way to do this, I'm all ears.

like image 288
Tyler Sebastian Avatar asked Jun 11 '18 19:06

Tyler Sebastian


People also ask

How do I use SSR in nextJS?

To use SSR for a page, we need to export an async function called “getServerSideProps“. This async function is called each time a request is made for the page. Note: In place of data you can take any other name of the variable. Also, you can pass multiple props by separating them with commas “,“.

Is nextJS only for SSR?

It facilitates developing Server-side rendered (SSR) React apps without starting over with create-react-app. Next. js routing and other built-in configurations are designed primarily for SSR and crawling towards Static Site Generation (SSG). But, there can be instances where you will not need SSR for one or more Next.

Can nextJS do client-side rendering?

Next. JS generally frowns on Client-Side Rendering, but that doesn't mean you can't fetch data from the Client at run time.

What is difference between getStaticProps and getServerSideProps?

getStaticProps(): A method that tells the Next component to populate props and render into a static HTML page at build time. getServerSideProps(): A method that tells the Next component to populate the props and render into a static HTML page at run time.


1 Answers

I have dig into this and my feeling is that this is not possible for multiple reason.

The setState update is async and won't be executed in your case.

The render of your provider will happen even before the state gets updated, so registration code will be execute later and the render function doesn't have the latest state

I put different console.log and below is what I got

Provider constructed with { mountedComponents: [],
  name: 'name-Sun Jun 24 2018 19:19:08 GMT+0530 (IST)' }
getDerivedStateFromProps
Renderring Provider Component { mountedComponents: [],
  name: 'name-Sun Jun 24 2018 19:19:08 GMT+0530 (IST)' }
data loaded
constructor Child { id: '1' } { registerComponent: [Function: value] }
Register Component called 1 { mountedComponents: [],
  name: 'name-Sun Jun 24 2018 19:19:08 GMT+0530 (IST)' }
Registering component 1
constructor Child { id: '2' } { registerComponent: [Function: value] }
Register Component called 2 { mountedComponents: [ '1' ],
  name: 'tarun-Sun Jun 24 2018 19:19:08 GMT+0530 (IST)' }
Registering component 2
constructor Child { id: '3' } { registerComponent: [Function: value] }
Register Component called 3 { mountedComponents: [ '1', '2' ],
  name: 'name-Sun Jun 24 2018 19:19:08 GMT+0530 (IST)' }
Registering component 3
constructor Child { id: '4' } { registerComponent: [Function: value] }
Register Component called 4 { mountedComponents: [ '1', '2', '3' ],
  name: 'name-Sun Jun 24 2018 19:19:08 GMT+0530 (IST)' }
Registering component 4

The information is actually only available when the componentDidMount occurs. But since in case of server side rendering that doesn't happen, you don't get the data.

I am digging further to see if any hacks are available, but as of now I am not sure

like image 79
Tarun Lalwani Avatar answered Sep 28 '22 05:09

Tarun Lalwani