使用Typescript使用getInitialProps将prop传递到Next.js中的每个页面

JavaScript React.js

樱小胖Mandy

2020-03-23

我遇到一种情况,我需要在页面呈现到服务器端并使用Next.js发送回给我之前,知道用户是否已登录,以避免UI发生闪烁变化。

我能够弄清楚如果用户已经使用此HOC组件登录,如何防止用户访问某些页面...

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;
};

这很棒。

现在,我如何构建类似的HOC组件,将其包装起来,比如说“ _app.tsx”,这样我就可以通过获取令牌并确定令牌是否过期并基于它来将“ userAuthenticated”属性传递给每个页面该道具我可以向用户显示适当的UI,而不会产生烦人的闪烁效果?

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));

因此,必须对每个页面都执行此操作,然后将属性传递到每个页面的全局布局中,而不是只在“ _app.tsx”中执行一次,这有点烦人。

我猜原因可能是因为“ _app.tsx”是类组件而不是像其余页面一样的功能组件?我不知道,我只是在猜测。

有什么帮助吗?

第2611篇《使用Typescript使用getInitialProps将prop传递到Next.js中的每个页面》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

0个回答

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android