Tengo un caso en el que necesito saber si el usuario ha iniciado sesión o no antes de que la página se muestre en el lado del servidor y me la envíe de nuevo usando Next.js para evitar cambios de parpadeo en la interfaz de usuario.
Pude descubrir cómo evitar que el usuario acceda a algunas páginas si ya inició sesión con este 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;
};
Y esto funciona muy bien.
Ahora, ¿cómo puedo construir un componente HOC similar para envolverlo? Digamos "_app.tsx" para que pueda pasar el accesorio "UserAuthenticated" a cada página obteniendo el token y averiguar si ha caducado o no y en función de ¿con qué accesorio puedo mostrar la IU adecuada al usuario sin ese molesto efecto de parpadeo?
Espero que me puedan ayudar con eso, traté de hacerlo de la misma manera que construí el HOC anterior, pero no pude hacerlo, especialmente porque TypeScript no lo hace más fácil con sus errores extraños :(
Editar == ==========================================
Pude crear dicho componente HOC y pasar el pro userAuthenticated
a cada página de esta manera ...
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;
};
Sin embargo, tuve que ajustar cada página con este HOC para pasar el accesorio userAuthenticated
al diseño global que tengo, porque no pude envolver el componente de clase "_app.tsx" con él, siempre me da un error. ..
Esto funciona ...
export default isAuthenticated(Home);
export default isAuthenticated(about);
Pero esto no ...
export default withRedux(configureStore)(isAuthenticated(MyApp));
Por lo tanto, es un poco molesto tener que hacer esto en todas y cada una de las páginas, y luego pasar el accesorio al diseño global en todas y cada una de las páginas en lugar de hacerlo una vez en el "_app.tsx".
Supongo que la razón puede ser porque "_app.tsx" es un componente de clase y no un componente de función como el resto de las páginas. No sé, solo estoy adivinando.
¿Alguna ayuda con eso?
ReactJS
sigue la Programación Funcional ni OOP, pero veo la mentalidad del desarrollo del backend en tu código con pensamientos de OOP. ¡Herede una nueva clase de otro componente! Didn't No lo vi así antes.