NextAuth 和 Next.js 到动态路由时出现问题,如“http://localhost:3000/profile/%5B%5D”

问题描述 投票:0回答:1

我目前正在使用 Next.js 开发一个网站,并且正在使用 Next.js 应用程序路由器。我已经集成了 NextAuth 来处理登录,到目前为止,用户创建和登录工作正常。

但是,我在登录后设置重定向时遇到了问题。目前,当我单击登录按钮时,我的提取会将我直接重定向到“/profile”页面。但是,我想创建一个动态路由来将用户重定向到“/profile/[userName]”之类的内容。

为了实现这一目标,我在“pages”目录中创建了一个文件“[userName]”,其中包含“page.jsx”。这个想法是,登录后,它应该带我到“/profile/[userName]”。但是,问题是,当我使用以下命令时,它要么总是将我重定向到“http://localhost:3000/profile”,要么将我定向到“http://localhost:3000/profile/%5B%5D”我的提取中的代码:

router.push(
/个人资料/[${userSlug}]
);
我也尝试过以下版本,但也不起作用:
router.push(
/个人资料/${String(userSlug)}
);

您能否帮助我理解为什么重定向未按预期工作以及如何解决此问题? 预先感谢您的帮助!”

这是我的登录页面:

"use client";

import { useState } from "react";

import { useFormik } from "formik";
import Image from "next/image";

import { signIn, useSession } from "next-auth/react";

import { useRouter } from "next/navigation";
import { redirect } from "next/navigation";

export default function Login({ params }) {
  const session = useSession();
  const { status } = useSession();
  let slug;
  const isAuthenticated = status === "Authenticated";

  const userName = session.data?.user?.name;
  const userSlug =
    userName && userName.includes(" ")
      ? userName.split(" ")[0].toLowerCase()
      : "";

  if (isAuthenticated) {
    return redirect("/");
  }
  const router = useRouter();
  const [error, setError] = useState([]);
  console.log("SESSION: ", session);

  const handleSubmit = async () => {
    const result = await signIn("credentials", {
      email: formik.values.email,
      password: formik.values.password,
      redirect: false,
    });
    if (result.error == null) {
      console.log("fetch", slug);
      router.push(`/profile/${String(userSlug)}`);
    }
    setError(result.error);
  };

  const formik = useFormik({
    initialValues: {
      email: "",
      password: "",
    },
    onSubmit: handleSubmit,
  });

  return (
    <section className="mt-8">
      <h1 className="text-center text-4xl mb-4">Login</h1>
      <form
        className="flex flex-col max-w-xs mx-auto"
        onSubmit={formik.handleSubmit}
        // onSubmit={handleSubmit}
      >
        {error && <div className="text-red-500">{error}</div>}
        <input
          type="email"
          name="email"
          placeholder="email"
          value={formik.values.email}
          // value={email}
          onChange={formik.handleChange}
          // onChange={(e) => setEmail(e.target.value)}
        />
        <input
          type="password"
          name="password"
          placeholder="password"
          value={formik.values.password}
          // value={password}
          onChange={formik.handleChange}
          // onChange={(e) => setPassword(e.target.value)}
        />
        <button type="submit">Login</button>
        <div className="my-4 text-center text-gray-500">
          or login with provider
        </div>
        <button
          type="button"
          alt="google logo"
          onClick={() => signIn("google", { callbackUrl: "/" })}
          className="flex gap-4 justify-center"
        >
          <Image src={"/google.png"} alt={""} width={24} height={24} />
          Login with google
        </button>
      </form>
    </section>
  );
}

这是我的身份验证route.js

import GoogleProvider from "next-auth/providers/google";
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcrypt";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

// export default NextAuth(authOptions);

const handler = NextAuth({
  // Configure one or more authentication providers
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
    CredentialsProvider({
      name: "credentials",
      credentials: {
        name: { label: "Name", type: "text" },
        email: {
          label: "Email",
          type: "email",
          placeholder: "[email protected]",
        },
      },
      // ...

      async authorize(credentials, req) {
        // Check to see if email and password are valid
        if (
          !credentials.email ||
          !credentials.password ||
          credentials.email === "" ||
          credentials.password === ""
        ) {
          throw new Error("Email and password are required");
        }

        // Check to see if the user exists
        const user = await prisma.user.findUnique({
          where: {
            email: credentials.email,
          },
        });

        if (!user) {
          throw new Error("User not found");
        }

        // Check to see if the password matches
        const passwordMatch = await bcrypt.compare(
          credentials.password,
          user.password
        );

        if (!passwordMatch) {
          throw new Error("Incorrect password");
        }

        // Return the user object if everything is valid
        return user;
      },

      // ...
    }),
    // ...add more providers here
  ],

  session: {
    strategy: "jwt",
  },
  secret: process.env.NEXTAUTH_SECRET,
  adapter: PrismaAdapter(prisma),
});

export { handler as GET, handler as POST };

我的尝试和期望(附加信息): 在尝试解决重定向问题时,我采取了以下操作:

  1. 我尝试将

    userSlug
    变量转换为字符串并在路线中使用它:

    router.push(`/profile/${String(userSlug)}`);
    

    但是,这并没有解决问题,重定向问题仍然存在。

  2. 作为测试,我直接在路由中设置用户名:

    router.push("/profile/john");
    

    令人惊讶的是,这按预期工作并将我重定向到“http://localhost:3000/profile/john。”

  3. 我尝试了不同的变化,包括从动态路线中删除方括号:

    router.push(`/profile/${userSlug}`);
    

    不幸的是,这也导致直接重定向到“http://localhost:3000/profile”,而不考虑动态值。

  4. 我从“profile”目录中删除了“page.js”文件,但这并没有给重定向行为带来任何变化。

next.js fetch prisma next-auth nextjs-dynamic-routing
1个回答
0
投票

当您知道用户已通过身份验证时,请使用 router.push()

if (isAuthenticated) {
    router.push(`profile/${userSlug}`)
  }
© www.soinside.com 2019 - 2024. All rights reserved.