是否可以使登录状态(例如以_app状态的用户对象的形式)/良好做法?
我在_app上有一个登录模式,该模式可以在成功的身份验证服务器端之后返回用户数据对象,然后将该对象设置为_app状态。 通过Context API,我可以将此登录状态移交给我的页面。
_app刷新时,有两种可能的方法:
SSR:在getInitialProps中,我可以从(express-session)req.session获取用户数据对象,并将其设置为构造函数中的_app状态。 CSR:当_app由于客户端导航而刷新时,状态保持不变,我的用户对象也保持不变。构造函数仅在SSR时调用。
所以我永远不需要cookie。...对吗?
编辑:关于构造函数,我错了。似乎它也被称为客户端。以前没有意识到这一点。...似乎有些奇怪。
EDIT2:奇怪的是,服务器和客户端日志上都记录了“ _app已构建” ...添加了_app代码段
class CustomApp extends App {
constructor(props) {
super(props);
// getInitialProps is static, therefore called before any other method (even constructor!).
// So in constructor we can already use the pageProps props which is returned by getInitialProps.
this.state = { user: this.props.user, openModal: false, csrfLoginToken: this.props.csrfLoginToken};
console.log("_app constructed. csfr=", this.state.csrfLoginToken);
}
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx);
}
if (!process.browser) {
console.log("_app renders on server, csrf: ",ctx.res.locals.csrfLoginToken);
//CSRF Token in res.locals when user not set
const csrfLoginToken = ctx.res.locals.csrfLoginToken
? ctx.res.locals.csrfLoginToken
: null;
//set user
//needed for full browser refreshes (via link, adress bar etc..)
//because _app loses state in that case, so we have to get it from session during ssr call
const user = ctx.req.session.user
? (ctx.req.session.user)
: null;
//status code
const {statusCode} = ctx.res
return { ...pageProps, csrfLoginToken, user, statusCode};
}
console.log("_app renders on client.");
return { ...pageProps};
}
...
handleNormalLogin = async (values) => {
console.log("_app got normal submit : csrf token to be sent:",this.state.csrfLoginToken);
this.handleClose();
const response = await apiLogin(values.email, values.password, this.state.csrfLoginToken);
if (response.ok) {
try {
const user = await response.json();
this.setState({ user: user });
this.setState({ csrfLoginToken: null });
Router.push({ pathname: "/bookings" }); //client-side navigation!
} catch (err) {
console.log("profile_err", err);
}
}
};