Pass prop to every single page in Next.js with gitInitialProps using Typescript

I have a case when I need to know if the user is logged in or not before the page gets rendered server-side and sent back to me using Next.js to avoid having flicker changes in the UI.

I was able to figure out how to prevent the user from accessing some pages if he is already logged in using this HOC component …

export const noAuthenticatedAllowed = (WrappedComponent: NextPage) => {
    const Wrapper = (props: any) => {
        return <WrappedComponent {...props} />;
    };

    Wrapper.getInitialProps = async (ctx: NextPageContext) => {
        let context = {};
        const { AppToken } = nextCookie(ctx);
        if (AppToken) {
            const decodedToken: MetadataObj = jwt_decode(AppToken);
            const isExpired = () => {
                if (decodedToken.exp < Date.now() / 1000) {
                    return true;
                } else {
                    return false;
                }
            };

            if (ctx.req) {
                if (!isExpired()) {
                    ctx.res && ctx.res.writeHead(302, { Location: "/" });
                    ctx.res && ctx.res.end();
                }
            }

            if (!isExpired()) {
                context = { ...ctx };
                Router.push("/");
            }
        }

        const componentProps =
            WrappedComponent.getInitialProps &&
            (await WrappedComponent.getInitialProps(ctx));

        return { ...componentProps, context };
    };

    return Wrapper;
};

And this works great.

Now, how can I build a similar HOC component to wrap it around let’s say “_app.tsx” so that I can pass “userAuthenticated” prop to every single page by getting the token and figure out if it is expired or not and based on that prop I can show the proper UI to the user without that annoying flickering effect?

I hope you can help me with that, I tried to do it the same way I built the above HOC, but I couldn’t do it, especially that Typescript doesn’t make this any easier with its weird errors 🙁

Edit ============================================

I was able to create such HOC component and pass down the pro userAuthenticatedto each page like this …

export const isAuthenticated = (WrappedComponent: NextPage) => {
    const Wrapper = (props: any) => {
        return <WrappedComponent {...props} />;
    };

    Wrapper.getInitialProps = async (ctx: NextPageContext) => {
        let userAuthenticated = false;

        const { AppToken} = nextCookie(ctx);
        if (AppToken) {
            const decodedToken: MetadataObj = jwt_decode(AppToken);
            const isExpired = () => {
                if (decodedToken.exp < Date.now() / 1000) {
                    return true;
                } else {
                    return false;
                }
            };

            if (ctx.req) {
                if (!isExpired()) {
                    // ctx.res && ctx.res.writeHead(302, { Location: "/" });
                    // ctx.res && ctx.res.end();
                    userAuthenticated = true;
                }
            }

            if (!isExpired()) {
                userAuthenticated = true;
            }
        }

        const componentProps =
            WrappedComponent.getInitialProps &&
            (await WrappedComponent.getInitialProps(ctx));

        return { ...componentProps, userAuthenticated };
    };

    return Wrapper;
};

However I had to wrap every single page with this HOC in order to pass down the prop userAuthenticated to the global layout that I have, because I couldn’t wrap the “_app.tsx” class component with it, it always gives me an Error …

This works …

export default isAuthenticated(Home);
export default isAuthenticated(about);

But this doesn’t …

export default withRedux(configureStore)(isAuthenticated(MyApp));

So it is a bit annoying having to do this to each and every page, and then pass down the prop to the global layout in each and every page instead of just do it once in the “_app.tsx”.

I’m guessing the reason may be because “_app.tsx” is a class component and not a function component like the rest of the pages?
I don’t know, I’m just guessing.

Any help with that?

Source: ReactJs