Typescript kullanarak getInitialProps ile Next.js'deki her bir sayfaya destek verin


10

Sayfa sunucu tarafında işlenir ve kullanıcı arabiriminde titreşim değişikliklerini önlemek için bana Next.js kullanarak bana gönderilmeden önce kullanıcı giriş olup olmadığını bilmek gerektiğinde bir durum var.

Kullanıcının zaten bu HOC bileşenini kullanarak giriş yaptığında bazı sayfalara erişmesini nasıl önleyebileceğimi anlayabildim ...

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

Ve bu harika çalışıyor.

Şimdi, etrafına sarmak için benzer bir HOC bileşenini nasıl oluşturabilirim "_app.tsx" diyelim, böylece "userAuthenticated" prop'ı her sayfaya geçirebilirim ve süresinin dolup dolmadığını belirleyip Bu pervane bu sinir bozucu titreme etkisi olmadan kullanıcıya uygun UI gösterebilir?

Umarım bana bu konuda yardımcı olabilirsiniz, yukarıdaki HOC'yi aynı şekilde yapmayı denedim, ama yapamadım, özellikle, Typcript'in garip hatalarıyla bunu daha kolay hale getirmediği :(


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

Böyle bir HOC bileşeni oluşturmak ve profesyonel userAuthenticatedgibi bu gibi her sayfaya geçmek başardı ...

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

Ancak pervane userAuthenticatedsahip olduğum küresel düzeni geçmek için her HOC ile bu tek sayfa sarmak zorunda kaldı , çünkü onunla "_app.tsx" sınıf bileşeni saramadı, her zaman bana bir Hata verir. ..

Bu çalışıyor ...

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

Ama bu ...

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

Bu nedenle, bunu her bir sayfaya yapmak ve daha sonra "_app.tsx" de bir kez yapmak yerine her bir sayfadaki pervane genel düzenine geçmek biraz can sıkıcı bir durum.

Ben "_app.tsx" bir sınıf bileşeni ve sayfaların geri kalanı gibi bir işlev bileşeni değil çünkü nedeni tahmin ediyorum? Bilmiyorum, sadece tahmin ediyorum.

Bununla ilgili herhangi bir yardım?

Yanıtlar:


5

Aynı sorunla karşılaşabilecekleriniz için bunu şu şekilde çözebildim ...

import React from "react";
import App from "next/app";
import { Store } from "redux";
import { Provider } from "react-redux";
import withRedux from "next-redux-wrapper";
import { ThemeProvider } from "styled-components";
import GlobalLayout from "../components/layout/GlobalLayout";
import { configureStore } from "../store/configureStore";
import { GlobalStyle } from "../styles/global";
import { ToastifyStyle } from "../styles/toastify";
import nextCookie from "next-cookies";
import jwt_decode from "jwt-decode";

 export interface MetadataObj {
   [key: string]: any;
 }

const theme = {
    color1: "#00CC99",
    color2: "#CC0000"
};

export type ThemeType = typeof theme;

interface Iprops {
    store: Store;
    userAuthenticated: boolean;
}

class MyApp extends App<Iprops> {
    // Only uncomment this method if you have blocking data requirements for
    // every single page in your application. This disables the ability to
    // perform automatic static optimization, causing every page in your app to
    // be server-side rendered.

    static async getInitialProps({ Component, ctx }: any) {
        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.isServer) {
                if (!isExpired()) {
                    userAuthenticated = true;
                }
            }

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

        return {
            pageProps: Component.getInitialProps
                ? await Component.getInitialProps(ctx)
                : {},
            userAuthenticated: userAuthenticated
        };
    }

    render() {
        const { Component, pageProps, store, userAuthenticated } = this.props;
        return (
            <Provider store={store}>
                <ThemeProvider theme={theme}>
                    <>
                        <GlobalStyle />
                        <ToastifyStyle />
                        <GlobalLayout userAuthenticated={userAuthenticated}>
                            <Component {...pageProps} />
                        </GlobalLayout>
                    </>
                </ThemeProvider>
            </Provider>
        );
    }
}

export default withRedux(configureStore)(MyApp);

Gördüğünüz gibi kullandığım paketleri görebilmek için _app.tsx bileşeninin tamamını yayınladım.

Ben kullanıyorum next-redux-wrapperve styled-componentsdaktilo versiyonu ile.

Ben yapmak zorunda appContextin gitInitialPropstürü itibarıyla anyaksi takdirde iş olmaz. Daha iyi bir typeöneriniz varsa lütfen bana bildirin. Türü kullanmaya çalıştım NextPageContext, ancak bu durumda bir nedenden dolayı işe yaramadı.

Ve bu çözümle, kullanıcının kimlik doğrulaması yapılıp yapılmadığını öğrenebildim ve her sayfada ve sayfa başına sayfa yapmak zorunda kalmadan kullanabilmem için küresel düzene bir pervane geçirebildim ve bu da Eğer userAuthenticatedpervaneye bağlı olmaları gerekiyorsa, üstbilgi ve altbilginin her seferinde oluşturulmasını istemezsiniz , çünkü şimdi üstbilgi ve altbilgiyi GlobalLayoutbileşene koyabilir ve yine de userAuthenticatedpervane hizmetinizde olabilir: D


Yorumum, yayınınız ve yanıtınızla ilgili değil. Söylemek istiyorum, ReactJSne Fonksiyonel Programlama ne de OOP izler, ama ben OOP düşünceleri ile kod size arka uç gelişimi zihniyet görüyorum. Başka bir bileşenden yeni bir sınıf miras alın! “Daha önce hiç böyle görmedim.
AmerllicA

1
Söylediklerinizi anlıyorum, sadece her şeyi denedim. Sorun SSR ile ilgili, "React App Oluştur" ile çalışıp "İstemci Tarafı Oluşturma" yapıyorum, bunu hiç yapmazdım, ama SSR ile başka bir şekilde çalışması için alamadım, Next.js tarafından önerilen yol bile.
Ruby
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.