如何保持我的next-auth用户会话并在其他路由中使用提供的ID获取数据?
P粉744691205
P粉744691205 2023-08-25 15:35:57
[React讨论组]
<p>我想在这里实现的是,每当用户登录时,我希望存储返回的数据,因为数据中包含一个我将在其他路由中使用的ID来获取数据。当用户成功登录后,他将被重定向到/home路由,并且从会话中获取的ID将用于获取数据。一切都正常工作,但如果我刷新主页,用户将变为空。</p> <p>这是我的[...nextauth].js文件的样子。</p> <pre class="brush:php;toolbar:false;">import NextAuth from &quot;next-auth&quot;; import CredentialsProvider from &quot;next-auth/providers/credentials&quot;; import axios from &quot;axios&quot;; export default NextAuth({ providers: [ CredentialsProvider({ name: &quot;credentials&quot;, credentials: { username: { label: &quot;Username&quot;, type: &quot;text&quot;, placeholder: &quot;justin&quot; }, password: {label: &quot;Password&quot;,type: &quot;password&quot;,placeholder: &quot;******&quot;}, }, async authorize(credentials, req) { const url = req.body.callbackUrl.split(&quot;/auth&quot;)[0]; const { username, password } = credentials; const user = await axios({ url: `${url}/api/user/login`, method: &quot;POST&quot;, data: { username: username, password: password, }, &quot;content-type&quot;: &quot;application/json&quot;, }) .then((res) =&gt; { return res.data; }) .catch((err) =&gt; { if (err.response.data) { throw new Error(err.response.data); } else { return null; } return null; }); return user; }, }), ], callbacks: { jwt: ({ token, user }) =&gt; { if (user) { token.user = user; } return token; }, session: ({ session, token }) =&gt; { if (token) { session.user = token.user; } return session; }, }, pages: { signIn: &quot;/auth/login&quot;, newUser: &quot;/auth/register&quot;, }, });</pre> <p>这是我的/home路由的样子</p> <pre class="brush:php;toolbar:false;">import Card from &quot;@/components/card/Card&quot;; import React, { useEffect, useState } from &quot;react&quot;; import styles from &quot;./home.module.css&quot;; import { Ubuntu } from &quot;@next/font/google&quot;; import { useSession } from &quot;next-auth/react&quot;; import { useDispatch, useSelector } from &quot;react-redux&quot;; const ubuntu = Ubuntu({ weight: &quot;500&quot;, subsets: [&quot;cyrillic&quot;] }); const getData = async (id) =&gt; { const res = await fetch({ url: &quot;http://localhost:3000/api/note/getall&quot;, method: &quot;POST&quot;, &quot;content-type&quot;: &quot;application/json&quot;, data: { id: id, }, }); if (!res.ok) { console.log(id); throw new Error(&quot;Unable to fetch&quot;); } else { return res.json(); console.log(res); } }; function home() { const colors = [&quot;#E9F5FC&quot;, &quot;#FFF5E1&quot;, &quot;#FFE9F3&quot;, &quot;#F3F5F7&quot;]; const random = Math.floor(Math.random() * 5); const rc = colors[random]; const [pop, setPop] = useState(&quot;none&quot;); const { user } = useSelector((state) =&gt; state.user); const getDataa = async () =&gt; { console.log(user) const data = await getData(user._id); console.log(data); }; useEffect(() =&gt; { if (user) { alert(user) } }, []); return ( &lt;div className={styles.home}&gt; &lt;header&gt; &lt;h3 className={ubuntu.className}&gt; Hello, &lt;br /&gt; {user?.username}! &lt;/h3&gt; &lt;input type=&quot;text&quot; placeholder=&quot;search&quot; /&gt; &lt;/header&gt; &lt;div className={styles.nav}&gt; &lt;h1 className={ubuntu.className}&gt;Notes&lt;/h1&gt; &lt;/div&gt; &lt;div className={styles.section}&gt; &lt;div className={styles.inner}&gt; {/* {data &amp;&amp; data.map((e) =&gt; ( &lt;Card rawData={e} color={colors[Math.floor(Math.random() * colors.length)]} /&gt; ))} */} &lt;/div&gt; &lt;/div&gt; &lt;div className=&quot;new&quot;&gt;&lt;/div&gt; &lt;/div&gt; ); } export default home;</pre></p>
P粉744691205
P粉744691205

全部回复(2)
P粉428986744

这段代码似乎会创建一个问题/竞争条件,因为你混合了两种不同的异步Promise处理方式:

const user = await axios({
  url: `${url}/api/user/login`,
  method: "POST",
  data: {
    username: username,
    password: password,
  },
  "content-type": "application/json",
})
  .then((res) => {
    return res.data;
  })
  .catch((err) => {
    if (err.response.data) {
      throw new Error(err.response.data);
    } else {
      return null;
    }
    return null;
  });
return user;

应该改成这样:

try {
  const user = await axios({
    url: `${url}/api/user/login`,
    method: "POST",
    data: {
      username: username,
      password: password,
    },
    "content-type": "application/json",
  });
  return user.data;
} catch (err) {
  if (err.response.data) {
    throw new Error(err.response.data);
  } else {
    return null;
  }
}

或者这样:

axios({
  url: `${url}/api/user/login`,
  method: "POST",
  data: {
    username: username,
    password: password,
  },
  "content-type": "application/json",
}).then((res) => {
  return res.data;
}).catch((err) => {
  if (err.response.data) {
    throw new Error(err.response.data);
  } else {
    return null;
  }
  return null;
});
P粉707235568

将此component添加到您的App.js文件中:

function Auth({ children }) {
  const router = useRouter();
  const { status } = useSession({
    required: true,
    onUnauthenticated() {
      router.push("/sign-in");
    },
  });

  if (status === "loading") {
    return 
Loading ...
; } return children; }

现在在您的App函数中,不再返回<Component {...pageProps} />,而是首先检查component是否具有auth属性,所以您将其包装在<Auth>中,以确保每个需要会话的组件只有在会话加载完成后才会挂载(这就是为什么用户为null,因为会话仍在加载中)

{
  Component.auth ? (
    
  ) : (
    
  );
}

最后,您将.auth = {}添加到您想要定义会话的每个页面中(在您的情况下是Home)

const Home = () => {
//....
}
Home.auth = {};

这还有助于在会话过期时将用户重定向到/sign-in页面

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号