Ho un caso in cui ho bisogno di sapere se l'utente ha effettuato l'accesso o meno prima che la pagina venga renderizzata sul lato server e rispedita a me usando Next.js per evitare modifiche dello sfarfallio nell'interfaccia utente.
Sono stato in grado di capire come impedire all'utente di accedere ad alcune pagine se ha già effettuato l'accesso utilizzando questo componente 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;
};
E questo funziona alla grande.
Ora, come posso costruire un componente HOC simile per avvolgerlo diciamo "_app.tsx" in modo da poter passare il prop "userAuthenticated" a ogni singola pagina ottenendo il token e capire se è scaduto o meno e basato su che prop posso mostrare all'utente l'interfaccia utente corretta senza quel fastidioso effetto di sfarfallio?
Spero che tu mi possa aiutare in questo, ho provato a farlo nello stesso modo in cui ho creato il HOC sopra, ma non ci sono riuscito, specialmente quel Typescript non lo rende più facile con i suoi strani errori :(
Modifica == ==========================================
Sono stato in grado di creare tale componente HOC e passare il pro userAuthenticated
ad ogni pagina in questo modo ...
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;
};
Tuttavia, ho dovuto avvolgere ogni singola pagina con questo HOC al fine di tramandare il userAuthenticated
layout al layout globale che ho, perché non ho potuto avvolgere il componente di classe "_app.tsx" con esso, mi dà sempre un errore. ..
Questo funziona ...
export default isAuthenticated(Home);
export default isAuthenticated(about);
Ma questo non ...
export default withRedux(configureStore)(isAuthenticated(MyApp));
Quindi è un po 'fastidioso dover fare questo per ogni singola pagina, e poi passare il prop al layout globale in ogni singola pagina invece di farlo una sola volta in "_app.tsx".
Immagino che il motivo potrebbe essere perché "_app.tsx" è un componente di classe e non un componente di funzione come il resto delle pagine? Non lo so, sto solo indovinando.
Qualche aiuto con quello?
ReactJS
segue la Programmazione Funzionale né OOP, ma vedo la mentalità dello sviluppo del backend nel tuo codice con pensieri OOP. Eredita una nuova classe da un altro componente! 😐Non l'avevo mai visto prima.