У меня есть случай, когда мне нужно знать, вошел ли пользователь в систему или нет, прежде чем страница будет обработана на стороне сервера и отправлена мне обратно с помощью Next. js, чтобы избежать мерцания изменений в пользовательском интерфейсе.
Мне удалось выяснить, как запретить пользователю доступ к некоторым страницам, если он уже вошел в систему с использованием этого компонента HO C ...
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;
};
И это прекрасно работает.
Теперь, как мне создать подобный компонент HO C, чтобы обернуть его, скажем, «_app.tsx», чтобы я мог передать «userAuthenticated» реквизит на каждую страницу, получив токен и выяснив, если срок его действия истек или нет, и на основании этого реквизита я могу показать пользователю правильный интерфейс без этого раздражающего мерцающего эффекта?
Надеюсь, вы можете помочь мне с этим, я пытался сделать это так же, как построил вышеупомянутый HO C, но я не смог этого сделать, тем более что Typescript не делает это проще с его странными ошибками :(
Edit ====== ====================================== * 1 015 *
Мне удалось создать такой компонент HO C и передать pro 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;
};
Однако мне пришлось обернуть каждую страницу этот HO C, чтобы передать реквизит userAuthenticated
в глобальный макет, который у меня есть, потому что я не мог обернуть его компонентом класса "_app.tsx", он всегда дает мне ошибку ...
Это работает ...
export default isAuthenticated(Home);
export default isAuthenticated(about);
Но это не ...
export default withRedux(configureStore)(isAuthenticated(MyApp));
Так что немного раздражает необходимость делать это с каждым страницу, а затем передайте реквизит глобальному макету на каждой странице вместо того, чтобы просто сделать это один раз в "_app.tsx".
Я предполагаю, что причина может быть в том, что "_app.tsx" "Является ли компонент класса, а не компонент функции, как остальные страницы? Я не знаю, я просто догадываюсь.
Помогите ли вы с этим?