टाइपस्क्रिप्ट का उपयोग करके getInitialProps के साथ Next.js में हर एक पृष्ठ पर प्रोप करें


10

मेरे पास एक ऐसा मामला है जब मुझे यह जानने की जरूरत है कि पेज में सर्वर-साइड दिए जाने से पहले उपयोगकर्ता लॉग इन है या नहीं, और UI में झिलमिलाहट वाले परिवर्तनों से बचने के लिए Next.js का उपयोग करके मुझे वापस भेज दिया।

मैं यह पता लगाने में सक्षम था कि उपयोगकर्ता को कुछ पन्नों तक पहुंचने से कैसे रोका जाए यदि वह इस 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 दिखा सकता हूं?

मुझे आशा है कि आप मेरी मदद कर सकते हैं, मैंने इसे उसी तरह से करने की कोशिश की थी जैसा मैंने उपरोक्त एचओसी का निर्माण किया था, लेकिन मैं ऐसा नहीं कर सका, खासकर कि टाइपस्क्रिप्ट अपनी अजीब त्रुटियों के साथ इसे आसान नहीं बनाता है :(


संपादित करें == ==========================================

मैं इस तरह के एचओसी घटक बनाने और userAuthenticatedइस तरह से प्रत्येक पृष्ठ के लिए समर्थक नीचे पारित करने में सक्षम था ...

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

हालाँकि, मुझे इस HOC के साथ हर एक पृष्ठ को लपेटना था, ताकि userAuthenticatedमेरे पास जो वैश्विक लेआउट है, उस प्रस्ताव को पास करने के लिए, क्योंकि मैं इसके साथ "_app.tsx" वर्ग घटक को लपेट नहीं सका, यह हमेशा मुझे एक त्रुटि देता है। ..

यह काम ...

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

लेकिन यह नहीं है ...

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

इसलिए प्रत्येक पृष्ठ पर ऐसा करना थोड़ा कष्टप्रद होता है, और फिर प्रत्येक और हर पृष्ठ में वैश्विक लेआउट के लिए प्रोप को नीचे कर दें, बजाय इसके कि आप एक बार "_app.tsx" करें।

मैं अनुमान लगा रहा हूं कि इसका कारण यह हो सकता है क्योंकि "_app.tsx" एक वर्ग घटक है और बाकी पृष्ठों की तरह एक फ़ंक्शन घटक नहीं है? मुझे नहीं पता, मैं सिर्फ अनुमान लगा रहा हूं।

उस के साथ कोई मदद?

जवाबों:


5

आप में से जो लोग एक ही मुद्दे पर आ सकते हैं, मैं इसे हल करने में सक्षम था ...

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

जैसा कि आप देखते हैं मैंने पूरे _app.tsx घटक को पोस्ट किया है ताकि आप उन पैकेजों को देख सकें जो मैं उपयोग कर रहा हूं।

मैं उपयोग कर रहा हूँ next-redux-wrapperऔर styled-componentsटाइपप्रति साथ।

मुझे टाइप के रूप appContextमें बनाना था , अन्यथा यह काम नहीं करेगा। इसलिए यदि आपके पास एक बेहतर सुझाव है तो कृपया मुझे बताएं। मैंने प्रकार का उपयोग करने की कोशिश की , लेकिन इस मामले में किसी कारण से काम नहीं किया।gitInitialPropsanytypeNextPageContext

और उस समाधान के साथ, मैं यह जानने में सक्षम था कि क्या उपयोगकर्ता प्रमाणित है या नहीं और वैश्विक लेआउट के लिए एक प्रस्ताव पारित करता है ताकि मैं इसे हर पेज में उपयोग कर सकूं और इसे प्रति पृष्ठ किए बिना कर सकूं और उस स्थिति में भी लाभ होगा यदि आप चाहते हैं कि हेडर और पाद को हर बार प्रस्तुत न किया जाए, यदि उन्हें userAuthenticatedप्रोप पर निर्भर रहना पड़े , क्योंकि अब आप हेडर और फुटर को GlobalLayoutघटक में रख सकते हैं और अभी भी userAuthenticatedआपके निपटान में प्रॉप है: D


मेरी टिप्पणी आपके पोस्ट और आपके उत्तर से संबंधित नहीं है। मैं कहता हूं, ReactJSकार्यात्मक प्रोग्रामिंग और न ही OOP का अनुसरण करता है, लेकिन मैं OOP विचारों के साथ आप में बैकएंड विकास की मानसिकता देखता हूं। एक अन्य घटक से एक नया वर्ग प्राप्त करें! 😐मैंने पहले जैसा नहीं देखा।
अमेरिकलीका

1
@AmerllicA मुझे वही मिल रहा है जो आप कह रहे हैं, मैंने बस सब कुछ करने की कोशिश की। मुद्दा SSR के साथ है, अगर मैं "क्रिएट रिएक्ट ऐप" के साथ काम कर रहा हूं और "क्लाइंट-साइड रेंडरिंग" कर रहा हूं, तो मैं ऐसा बिल्कुल नहीं करूंगा, लेकिन मैं इसे एसएसआर के साथ किसी अन्य तरीके से काम करने के लिए नहीं कर सका, यह Next.js. द्वारा भी अनुशंसित तरीका है
रूबी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.