如何使用 Next.js^9.3 将 cookie 信息从 SignupPage 填充到 Navbar 组件?
How to populate cookies infos from SignupPage to the Navbar component with Next.js^9.3?
2 天以来,我一直在努力实施身份验证。
我使用 Strapi 作为无头 CMS/backend。 我使用 next.js@9.3.4 作为前端。
我从教程中找到了一个名为 nookie 的软件包。
我有一个注册页面,我在其中实现了 nookies,但因为我想显示 用户名 和 link 让用户 logout 退出,我决定将所有内容放在 React context 中(不知道是否这是个好主意。
在我 刷新页面之前一切正常。 cookie 仍然存在 但 用户名和 link消失
这是注册页面
import cogoToast from 'cogo-toast';
import Router from 'next/router';
import { parseCookies } from 'nookies';
import styled from 'styled-components';
import FormStyles from '../components/styles/FormStyles';
import Title from '../components/Title';
import { signupUser } from '../lib/api';
import useForm from '../lib/useForm';
import { useInfos } from './context/LocalState';
// import { useState, useEffect } from 'react';
const Column = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 20px;
`;
const SignUpPage = () => {
const { inputs, handleChange, clearForm } = useForm({
username: 'machin',
email: 'machin@850g.com',
password: 'azerty123',
});
const { userLogin } = useInfos();
const isEmpty = !inputs.username || !inputs.email || !inputs.password;
const handleSubmit = async e => {
e.preventDefault();
const res = await signupUser(
inputs.username,
inputs.email,
inputs.password
);
userLogin(res);
clearForm();
};
return (
<Column>
<FormStyles method="post" onSubmit={handleSubmit}>
<fieldset>
<Title title="Se creer un Compte" center />
{isEmpty && (
<p className="form-empty">Pense a remplir tous les champs</p>
)}
<label htmlFor="username">
Username
<input
type="text"
name="username"
value={inputs.username}
onChange={handleChange}
autoComplete="name"
/>
</label>
<label htmlFor="email">
Email
<input
type="email"
name="email"
value={inputs.email}
onChange={handleChange}
autoComplete="email"
/>
</label>
<label htmlFor="password">
Password
<input
type="password"
name="password"
value={inputs.password}
onChange={handleChange}
autoComplete="new-password"
/>
</label>
{!isEmpty && <button type="submit">Sign Up</button>}
</fieldset>
</FormStyles>
</Column>
);
};
SignUpPage.getInitialProps = ctx => {
const isAuthenticated = parseCookies(ctx).coookiePapi;
console.log({ isAuthenticated });
// When the user is authenticated, don't let the user visit the
// sign-in and sign-up routes
if (isAuthenticated && ['/signup', '/signin'].indexOf(ctx.asPath) > -1) {
if (typeof window !== 'undefined') {
Router.push('/');
cogoToast.info("You're already logged papi");
} else if (ctx.res) {
ctx.res.writeHead(301, {
Location: '/',
});
ctx.res.end();
}
}
return {};
};
export default SignUpPage;
我的 2 个函数来自 React Context
const userLogin = info => (
setCookie(null, 'coookiePapi', info.jwt, {
maxAge: 30 * 24 * 60 * 60,
path: '/',
}),
setUser(info),
info.jwt
? cogoToast.success("great {info.user.username}!")
: cogoToast.error("Something went wrong"),
Router.push('/')
);
const userLogout = () => (
destroyCookie(null, 'cookiePapi'),
Router.push('/'),
setUser([]),
cogoToast.success('See you soon')
);
React 应用上下文将在页面刷新时重置,您需要编写自己的 persistence
逻辑。我不确定你的 setUser
功能是做什么的,但你需要做两件事:
a) 当用户状态改变时在登录时写入存储。我们可以通过一个effect hook来实现(当userState改变时,持久化到localStorage):
useEffect(() => {
localStorage.setItem('userState', JSON.stringify(userDetails))
}, [userDetails])
b) 更新您的上下文/状态代码以从 localStorage 恢复。例如,
let initialUserState = {}
try {
initialUserState = JSON.parse(window.localStorage.getItem('userState'))
} catch(e) { // do nothing }
const [userState, setUserState] = useState(initialUserState);
use-persisted-state 简化了这个过程,还为您提供了助手来处理应用内状态和存储同步。
由于您将 localStorage 或 sessionStorage 视为存储,因此您可以有效地脱离全局应用程序上下文,并使用定制的挂钩,例如 useUserState
,在需要引用您的组件的内部用户状态。
2 天以来,我一直在努力实施身份验证。 我使用 Strapi 作为无头 CMS/backend。 我使用 next.js@9.3.4 作为前端。
我从教程中找到了一个名为 nookie 的软件包。 我有一个注册页面,我在其中实现了 nookies,但因为我想显示 用户名 和 link 让用户 logout 退出,我决定将所有内容放在 React context 中(不知道是否这是个好主意。
在我 刷新页面之前一切正常。 cookie 仍然存在 但 用户名和 link消失
这是注册页面
import cogoToast from 'cogo-toast';
import Router from 'next/router';
import { parseCookies } from 'nookies';
import styled from 'styled-components';
import FormStyles from '../components/styles/FormStyles';
import Title from '../components/Title';
import { signupUser } from '../lib/api';
import useForm from '../lib/useForm';
import { useInfos } from './context/LocalState';
// import { useState, useEffect } from 'react';
const Column = styled.div`
display: grid;
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
gap: 20px;
`;
const SignUpPage = () => {
const { inputs, handleChange, clearForm } = useForm({
username: 'machin',
email: 'machin@850g.com',
password: 'azerty123',
});
const { userLogin } = useInfos();
const isEmpty = !inputs.username || !inputs.email || !inputs.password;
const handleSubmit = async e => {
e.preventDefault();
const res = await signupUser(
inputs.username,
inputs.email,
inputs.password
);
userLogin(res);
clearForm();
};
return (
<Column>
<FormStyles method="post" onSubmit={handleSubmit}>
<fieldset>
<Title title="Se creer un Compte" center />
{isEmpty && (
<p className="form-empty">Pense a remplir tous les champs</p>
)}
<label htmlFor="username">
Username
<input
type="text"
name="username"
value={inputs.username}
onChange={handleChange}
autoComplete="name"
/>
</label>
<label htmlFor="email">
Email
<input
type="email"
name="email"
value={inputs.email}
onChange={handleChange}
autoComplete="email"
/>
</label>
<label htmlFor="password">
Password
<input
type="password"
name="password"
value={inputs.password}
onChange={handleChange}
autoComplete="new-password"
/>
</label>
{!isEmpty && <button type="submit">Sign Up</button>}
</fieldset>
</FormStyles>
</Column>
);
};
SignUpPage.getInitialProps = ctx => {
const isAuthenticated = parseCookies(ctx).coookiePapi;
console.log({ isAuthenticated });
// When the user is authenticated, don't let the user visit the
// sign-in and sign-up routes
if (isAuthenticated && ['/signup', '/signin'].indexOf(ctx.asPath) > -1) {
if (typeof window !== 'undefined') {
Router.push('/');
cogoToast.info("You're already logged papi");
} else if (ctx.res) {
ctx.res.writeHead(301, {
Location: '/',
});
ctx.res.end();
}
}
return {};
};
export default SignUpPage;
我的 2 个函数来自 React Context
const userLogin = info => (
setCookie(null, 'coookiePapi', info.jwt, {
maxAge: 30 * 24 * 60 * 60,
path: '/',
}),
setUser(info),
info.jwt
? cogoToast.success("great {info.user.username}!")
: cogoToast.error("Something went wrong"),
Router.push('/')
);
const userLogout = () => (
destroyCookie(null, 'cookiePapi'),
Router.push('/'),
setUser([]),
cogoToast.success('See you soon')
);
React 应用上下文将在页面刷新时重置,您需要编写自己的 persistence
逻辑。我不确定你的 setUser
功能是做什么的,但你需要做两件事:
a) 当用户状态改变时在登录时写入存储。我们可以通过一个effect hook来实现(当userState改变时,持久化到localStorage):
useEffect(() => {
localStorage.setItem('userState', JSON.stringify(userDetails))
}, [userDetails])
b) 更新您的上下文/状态代码以从 localStorage 恢复。例如,
let initialUserState = {}
try {
initialUserState = JSON.parse(window.localStorage.getItem('userState'))
} catch(e) { // do nothing }
const [userState, setUserState] = useState(initialUserState);
use-persisted-state 简化了这个过程,还为您提供了助手来处理应用内状态和存储同步。
由于您将 localStorage 或 sessionStorage 视为存储,因此您可以有效地脱离全局应用程序上下文,并使用定制的挂钩,例如 useUserState
,在需要引用您的组件的内部用户状态。