Since I’ve discovered next.js I fell in love with its simplicity and flexibility. Server side rendered React was finally a trivial thing to do.

While using it extensively I eventually started to initialize a lot of things in top level pages. Layout boilerplate, common UI components, analytics, and so on.

I also wanted to initialize things depending on server side variables, such as the user-agent string. Or to always initialize a prop such as a language for all my pages. I quickly ended up with a getInitialsProps looking like this everywhere:

The problem is I had to copy/paste this portion in each one of my pages. Putting it in a layout component wouldn’t work because getInitialProps is not a standard React lifecycle. Next only calls getInitialProps on top level Page components inside the pages folder.

Solution: PageWrapper HOC

This pattern abstract away the logic inside a higher order component

You then use it in any page you want to inject the props into:

export PageWrapper(MyPage)

UPDATE for next.js ≥ 6

Starting Next.js 6 we can now use the _app.js file to define an App Component that will wrap every other pages. This is exactly what we need and it reduces the amount of manual work (writing export PageWrapper(MyPage) for every pages).

This will ensure all our pages are automatically wrapped inside the PageWrapper!

How does this work ?

PageWrapper is a function which accept a child React component as a parameter. It returns a higher order React component which render the child and transfer all its props down. It essentially just abstracts away the getInitialProps call in a dedicated component.

You’re still able to implement getInitialProps in the child component: PageWrapper will call it and merge the resulting props together before passing them down.

Practical Case

I often use user-agent detection in my next apps and the initialization is quite painful without the PageWrapper pattern:

Now with the PageWrapper

Now I can just export PageWrapper(MyPage) and all the user-agent boilerplate will be taken care of for me!

Conclusion

With the PageWrapper pattern you can abstract common boilerplate that requires access to server side variables. You can also fetch common data requirements for all your pages.

A concrete example is adding user-agent awareness to your app. The component I used to make the example comes from my react-useragent library.

If you enjoyed this article make sure to follow me to be notified for more! You can also hit the heart to contribute to my ego ♥

Also I might be more eloquent (and even funny) on Twitter