I asked the same question in teratail, but after 2 weeks, I still have 0 answers, so I would like to ask you a question.
I don't care which way you answer.Also, I will share the progress with both of them.Thank you for your cooperation.
To study Next.js+TypeScript, we are trying to modify the repository below.
https://github.com/jasonraimondi/nextjs-jwt-example
I didn't know how to write getServerSideProps in Component, so I got stuck.
web/components/private_route.tsx
import ServerCookie from "next-cookies";
import Router from "next/router";
import React, {Component} from "react";
import {COOKIES} from "../services/login_service";
import {AuthToken} from "../services/auth_token";
export type AuthProps = {
auth —AuthToken
}
export function privateRoute (WrappedComponent: any) {
return class extensions Component <AuthProps > {
static async getInitialProps (ctx:any) {
const token=ServerCookie(ctx) [COOKIES.authToken];
const auth = new AuthToken(token);
const initialProps={auth};
if(auth.isExpired){
ctx.res.writeHead(302,{
Location: "/login?redirected=true",
});
ctx.res.end();
}
if(WrappedComponent.getInitialProps) returnWrappedComponent.getInitialProps(initialProps);
return initialProps;
}
get auth(){
// The server pass to the client serializes the token
// so have to reinitialize the authToken class
//
// @see https://github.com/zeit/next.js/issues/3536
return new AuthToken (this.props.auth.token);
}
render() {
return<WrappedComponent auth={this.auth}{...this.props}/>
}
};
}
Next.js9.3 and later recommend getServerSideProps instead of getInitialProps, so
I would like to rewrite it to the following form.
import ServerCookie from "next-cookies";
import Router from "next/router";
import React, {Component} from "react";
import {COOKIES} from "../services/login_service";
import {AuthToken} from "../services/auth_token";
import {GetServerSideProps} from "next";
export type AuthProps = {
auth —AuthToken
}
export function privateRoute (WrappedComponent: any) {
return class extensions Component <AuthProps > {
// static async getInitialProps (ctx:any) {
// const token=ServerCookie(ctx) [COOKIES.authToken];
// const auth = new AuthToken(token);
// const initialProps={auth};
// if(auth.isExpired){
// ctx.res.writeHead(302,{
// Location: "/login?redirected=true",
// });
// ctx.res.end();
// }
// if(WrappedComponent.getInitialProps) returnWrappedComponent.getInitialProps(initialProps);
// return initialProps;
// }
get auth(){
// The server pass to the client serializes the token
// so have to reinitialize the authToken class
//
// @see https://github.com/zeit/next.js/issues/3536
return new AuthToken (this.props.auth.token);
}
render() {
return<WrappedComponent auth={this.auth}{...this.props}/>
}
};
}
export cost getServerSideProps:GetServerSideProps=async(ctx:any)=>{
const token=ServerCookie(ctx) [COOKIES.authToken];
const auth = new AuthToken(token);
const initialProps={auth};
if(auth.isExpired){
ctx.res.writeHead(302,{
Location: "/login?redirected=true",
});
ctx.res.end();
}
if(WrappedComponent.getInitialProps) returnWrappedComponent.getInitialProps(initialProps);
return initialProps;
}
When I actually rewritten it as above,
(1) I want to use the prop I'm returning with getServerSideProps in the privateRoute function, but I don't know how to pass it.
(2) If(WrappedComponent.getInitialProps) returnWrappedComponent.getInitialProps(initialProps); in the section "WrappedComponent" does not find the name 'WrappedComponent' and I do not know how to rewrite to getServerSideProps instead of getInitialProps.
There is a problem that has occurred and it is clogged up.
(1)As for , I thought it should be function Page({data}){ as explained in the official document, but in the case of this code, I take WrappedComponent as an argument in Component, so I don't know how to write it.
https://nextjs.org/docs/basic-features/data-fetching#simple-example-1
By the way, this Component is
web/pages/dashboard.tsx
This is a component used in and for creating pages that can only be seen when logging in, and is used in the Page code in a way similar to "export default privateRoute (Page);"
(1) and (2) How can we solve this problem?
Both Next.js TypeScript are beginners, so I'm sorry if I'm misguided.I would appreciate it if you could point it out.
Read official documentation about getServerSideProps
I searched GitHub for similar codes and tried to find ways to write them for a few days, but I didn't know.
Next.js 9.5
TypeScript 3.5
getServerSideProps
cannot be used with getInitialProps
.
(Maybe it's possible, but I'm thinking about merging prop's from two sources, which makes me more hellish.)
getServerSideProps
(and getInitialProps
) are exported from the pages/
files below, so they are not handled by the following files:
components/
The components below must receive the initial state from the pages/
Page components below, either Props or per state management framework.
extjs-jwt-example
defaults export the Component generated by privateRoute()
from the pages/
file, so the pages/nantoka.tsx#default.getInitialProps
file is resolved directly from the file.
getServerSideProps
cannot be used with getInitialProps
.
(Maybe it's possible, but I'm thinking about merging prop's from two sources, which makes me more hellish.)
getServerSideProps
(and getInitialProps
) are exported from pages/
files, so they are not handled by components/
files.
Components below components/
must receive the initial state from the pages/
Page components below, or per state management framework.
extjs-jwt-example
defaults export the Component generated by privateRoute()
from the pages/
file, so the pages/nantoka.tsx#default.getInitialProps
file is resolved directly from the file.
Therefore, I think the reasonable design is as follows.
(Please put the file according to the project.)
export const getOrForbidenAuthToken=(ctx:GetServerSidePropsContext)=>{
const token=ServerCookie(ctx) [COOKIES.authToken]
const auth=new AuthToken(token)
if(auth.isExpired){
ctx.res.writeHead(302,{
Location: '/login?redirected=true',
})
ctx.res.end()
// Verify that there is no problem with handling exceptions roughly
return null
}
return auth
}
//web/components/private_route.tsx
export function privateRoute<Pextends {auth:AuthToken}>(
WrappedComponent—ComponentType<P>
) {
// Receive serialized auth in getServerSideProps
return({auth,...props}:{auth:AuthToken}&P)=>{
// Create instances only when mounting components (google useMemo)
const token=useMemo()=>new AuthToken(auth.token), [auth])
// Hand over the AuthToken instance to WrappedComponent (forgive me as any)
return<WrappedComponent auth={token}{...(props as any)}/>
}
}
//pages/nantoka.tsx
import {getOrForbidenAuthToken} from '~yourapp/auth'
export const Page=privateRoute({auth}:{auth:AuthToken})=>{
return<div>do something here</div>
})
export default Page
export cost getServerSideProps:GetServerSideProps=async(ctx)=>{
// Call getOrForbidenAuthToken to return an error response, etc.
const auth=getOrForbidenAuthToken(ctx)
// Even if there is an error in authentication, it will be processed from then on (this line).
/ Please guard if(auth!=null) or whatever action you need to authenticate.
return {props:{auth}}
}
That's it.
© 2024 OneMinuteCode. All rights reserved.