- 目标:**我希望在 * 已登录用户 * 尝试手动转到/auth/signin时将其重定向到主页。
登录页面/组件:
const Signin = ({ currentUser }) => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const { doRequest, errors } = useRequest({
url: '/api/users/signin',
method: 'post',
body: {
email, password
},
onSuccess: () => Router.push('/')
});
useEffect(() => {
const loggedUser = () => {
if (currentUser) {
Router.push('/');
}
};
loggedUser();
}, []);
自定义应用程序组件(_A):
const AppComponent = ({ Component, pageProps, currentUser }) => {
return (
<div>
<Header currentUser={currentUser} />
<Component {...pageProps} currentUser={currentUser} />
</div>
)
};
AppComponent.getInitialProps = async (appContext) => {
const client = buildClient(appContext.ctx);
const { data } = await client.get('/api/users/currentuser');
let pageProps = {};
if (appContext.Component.getInitialProps) {
pageProps = await appContext.Component.getInitialProps(appContext.ctx);
}
return {
pageProps,
...data
}
};
export default AppComponent;
- 版本**:
我试过了,但是这会导致一个轻微的延迟,因为它不会在服务器端渲染。延迟的意思是:在重定向之前,它会显示我不想显示的页面一秒钟左右。
我可以使用加载标志或一堆if else条件,但这是一种变通方法,处理此问题的最佳方法/实践是什么?
我想出了另一个解决办法:
- 我建立了一个重定向钩子:
import Router from 'next/router';
export default (ctx, target) => {
if (ctx.res) {
// server
ctx.res.writeHead(303, { Location: target });
ctx.res.end();
} else {
// client
Router.push(target);
}
}
- 然后,我做了2 HOC(登录和注销用户)到受保护的路由:
import React from 'react';
import redirect from './redirect';
const withAuth = (Component) => {
return class AuthComponent extends React.Component {
static async getInitialProps(ctx, { currentUser }) {
if (!currentUser) {
return redirect(ctx, "/");
}
}
render() {
return <Component {...this.props} />
}
}
}
export default withAuth;
- 然后我用它 Package 组件以保护页面:
export default withAuth(NewTicket);
有什么更好的方法来处理这个问题吗?我真的很感激你的帮助。
8条答案
按热度按时间eqzww0vc1#
答案
我真的建议你看看例子,看看NextJS建议如何处理这一点。资源真的很好!
https://github.com/vercel/next.js/tree/master/examples
例如,您可以使用
next-auth
,这是一个开源身份验证选项。示例在这里。https://github.com/vercel/next.js/tree/master/examples/with-next-auth
因此,上面的选项是默认服务器端呈现的应用程序,因为我们使用/api路径进行身份验证。如果你想要一个无服务器的解决方案,你可能必须将/api路径中的所有内容拉到一个lambda(AWS Lambda)+一个网关api(AWS Api Gateway)中。你所需要的只是一个连接到该api的自定义钩子。当然,你也可以通过不同的方式来实现这一点。
下面是另一个使用firebase的身份验证示例。
https://github.com/vercel/next.js/tree/master/examples/with-firebase-authentication
另一个例子是使用Passport.js
https://github.com/vercel/next.js/tree/master/examples/with-passport
您还询问了加载行为,这个示例可能会对您有所帮助
https://github.com/vercel/next.js/tree/master/examples/with-loading
🙌
意见
custom_app组件通常是一个顶级 Package 器(top_document并不完全符合这种描述)。
实际上,我会在_app下面创建一个Login组件,通常我会在Layout组件中实现该模式,或者像上面的示例一样,使用api路径或实用程序函数。
mw3dktmi2#
下面是一个使用getServerSideProps的自定义"钩子"的示例。
我使用的是react-query,但是您可以使用任何数据获取工具。
sauutmhj3#
将NextJs升级到9.3+并使用
getServerSideProps
而不是getInitialProps
。getServerSideProps
仅运行,并且始终在服务器端运行,这与getInitialProps
不同。如果身份验证失败,请从getServerSideProps
重定向。aiazj4mn4#
在这里,在未来9++你可以这样做,只是检查会话,如果没有,我们可以返回一个目的地重定向路由用户到终点!
hzbexzde5#
我想进一步解释一下@Nico在他的评论中所说的话。下面是我的设置:
Layout.tsx
文件和
withAuth.js
文件rxztt3cl6#
我也遇到过同样的问题,我的客户端解决方案不 Flink 的内容如下:如果我用错了方法,请纠正我。我使用
useRouter
当我想要保护路由时,我使用以下语法:
aamkag617#
现在将此代码添加到您的_app. js中
Evrything现在应该工作,如果你想添加加载。
mu0hgdu08#
Vercel最近引入了middleware for Next.js.Next.js中间件,允许您在处理HTTP请求之前运行代码。
要将中间件逻辑添加到应用,请在Next.js项目的根目录中添加
middleware.js
或middleware.ts
文件。