import React from "react" ; import Head from "next/head" ; import { ApolloClient } from "apollo-client" ; import { NormalizedCacheObject } from "apollo-cache-inmemory" ; import PropTypes from "prop-types" ; import { getDataFromTree } from "react-apollo" ; import initApollo from "./initApollo" ; import { isBrowser } from "./isBrowser" ; import redirect from "./redirect" ; export default ( App ) => class WithData extends React . Component { static displayName = `WithData(${ App . displayName })` ; static propTypes = { apolloState : PropTypes . object . isRequired } ; static async getInitialProps ( ctx ) { const { Component , router , ctx : { res } } = ctx ; const apollo = initApollo ( { } ) ; ctx . ctx . apolloClient = apollo ; let appProps = { } ; if ( App . getInitialProps ) { appProps = await App . getInitialProps ( ctx ) ; } if ( res && res . finished ) { return { } ; } if ( ! isBrowser ) { try { await getDataFromTree ( < App { ... appProps } Component = { Component } router = { router } apolloClient = { apollo } / > ) ; } catch ( error ) { console . error ( "Error while running `getDataFromTree`" , error ) ; if ( error . message . includes ( "Access denied! You need to be authorized to perform this action!" ) ) { redirect ( ctx . ctx , "/users/login" ) ; } } Head . rewind ( ) ; } const apolloState = apollo . cache . extract ( ) ; return { ... appProps , apolloState } ; } apolloClient : ApolloClient < NormalizedCacheObject > ; constructor ( props ) { super ( props ) ; this . apolloClient = initApollo ( props . apolloState ) ; } render ( ) { return < App { ... this . props } apolloClient = { this . apolloClient } / > ; } } ;