Next.js: HOC not calling getInitialProps

Created on 24 Jan 2019  路  12Comments  路  Source: vercel/next.js

I'm trying to create a HOC for withCurrentUser like this:

import React, { Component } from 'react';

export default WrappedComponent =>
  // eslint-disable-next-line react/prefer-stateless-function
  class extends Component {
    static getInitialProps({ apollo }) {
      console.log('it called me');
      console.log(apollo);

      return { hello: "world" };
    }

    render() {
      return (
        <>
          <h1>hello from withCurrentUser</h1>
          <WrappedComponent {...this.props} />
        </>
      );
    }
  };

and then trying to use like this:

import React from 'react';

import withCurrentUser from '../../hocs/withCurrentUser';

const NavBar = ({ hello }) => <h1>NavBar {hello}</h1>;

export default withCurrentUser(NavBar);

But it's not calling getInitialProps. What am I doing wrong?

Most helpful comment

I guess we'll have to make the warning clearer here: https://github.com/zeit/next.js#fetching-data-and-component-lifecycle

Note: getInitialProps can not be used in children components. Only in pages.

All 12 comments

'getInitialProps' would only be called when the component is in the folder './pages'. Have you put the file of the second part of code exactly in './pages'?

No, it's a NavBar component. The idea was to have a NavBar with the current user using a HOC technique as Spectrum.chat does. But apparently it doesn't work as I expected.

I guess we'll have to make the warning clearer here: https://github.com/zeit/next.js#fetching-data-and-component-lifecycle

Note: getInitialProps can not be used in children components. Only in pages.

@timneutkens I did it different, I don't actually need to get the apollo client from getInitialprops, I can just make usage of the Query component and it will, the reason for that is because I'm wrapping the _app.js with the withApollo HOC that has the ApolloProvider in it.
I just created a HOC using Query and called the WrappedComponent passing the current user data as props.

I wrapped a page with a withAuth HOC and the page's getInitialProps cannot be called as a result.The authentication function using the withAuth HOC works; however, the Contact's getInitialProps function is not called as a result

Anyway to work around this?

Contact Page

import Layout from "../components/Layout";
import { withAuth } from "../services/withAuth";

class Contact extends React.Component {
  static async getInitialProps(ctx) {
    console.log("@contact authenticated ", ctx);
    return {};
  }
  render() {
    return (
      <Layout>
        <p>hey there</p>
        <a href="mailto:[email protected]">[email protected]</a>
      </Layout>
    );
  }
}

export default withAuth(Contact);

withAuth HOC

import { ME } from "../graphql/queries";
import redirect from "../lib/redirect";

export const withAuth = C => {
  class AuthComponent extends React.Component {
    static async getInitialProps(ctx) {
      const response = await ctx.apolloClient.query({ query: ME });
      console.log("@withAuth ", response);
      if (!response || !response.data || !response.data.me) {
        redirect(ctx, "/");
        return {
          me: null
        };
      }

      return {
        me: response.data.me
      };
    }

    render() {
      return <C {...this.props} />;
    }
  }

  return AuthComponent;
};

You have to call C.getInitialProps(...) in HOC.getInitialProps(...);

const pageProps = await C.getInitialProps && C.getInitialProps(ctx);

Hi @jim-king-2000 , can't seem to work. it throws a circular reference error

Hi @jim-king-2000 , it works now. i passed the entire ctx object to the return value hence it throws the circular reference error. however, if i destructure the ctx and pass on only the destructured values, it works fine. Thanks for your sharing

@myhendry can you show me code how you destructed the ct and passed only destructed values I am facing similar issue

@myhendry I didn't notice anything destructuring on the stackoverflow issue. Please she'd more light

@myhendry You need to contain the static methods in the HOC.

export function withAuth (WrappedComponent) {
  return class extends Component {
    constructor(props) {
      super(props)
    }

    static getInitialProps = WrappedComponent.getInitialProps

    render () {
      return <WrappedComponent {...this.props} />
    }
  }
}

Here is the official docs from React:
https://reactjs.org/docs/higher-order-components.html#static-methods-must-be-copied-over

Was this page helpful?
0 / 5 - 0 ratings