英文:
useRouter().push() from "next/navigation" doesn't work on custom signIn-Page with next-auth
问题
After a successful login on my custom signIn-Page, I use with next-auth, I'm trying to redirect back to the callbackUrl, but that doesn't work. I'm using react 18.2.0, next 13.4.8-canary.2 and next-auth 4.22.1.
signIn-Page (\src\app\api\auth\signin\page.js):
"use client";
import { signIn } from "next-auth/react";
import { useSearchParams, useRouter } from "next/navigation";
import { useState } from "react";
export default function LoginPage() {
const router = useRouter();
const callbackUrl = useSearchParams().get("callbackUrl") || "/";
const course = callbackUrl.split("/").pop();
let [loading, setLoading] = useState(false);
let [password, setPassword] = useState("");
const [error, setError] = useState("");
async function onSubmit(event) {
event.preventDefault();
try {
setLoading(true);
const res = await signIn("credentials", {
redirect: false,
courseName: course,
password: password,
callbackUrl
});
if (!res?.error) {
setError("");
console.log(`tryin to redirect to ${callbackUrl}`);
router.push(callbackUrl);
} else {
setError("falsches Passwort");
}
setLoading(false);
} catch (error) {
setLoading(false);
setError(error);
}
}
function handleChange(event) {
event.preventDefault();
setPassword(event.target.value);
}
return (
<main style={{ display: "flex", justifyContent: "center" }}>
<div className="LoginContainer">
<br />
<div className="LoginBackgroundImage">
<h1 className="LoginHeading">Login</h1>
</div>
<form onSubmit={onSubmit}>
{error ? <strong className="w3-text-red">{error}</strong> : ""}
<div>
<p style={{ margin: 5 }}>
<strong>{course}</strong>
</p>
</div>
<div>
<input
className="passwordField"
required
type="password"
name="password"
value={password}
onChange={handleChange}
placeholder="Passwort"
/>
</div>
<button className="loginButton" type="submit" disabled={loading}>
{loading ? "lädt..." : "Anmelden"}
</button>
</form>
</div>
</main>
);
}
As you can see from the path, I'm using the new /app directory for routing. I know the login process is working because I can then call the callbackUrl manually in the browser, and the content that requires authorization is displayed. I can also see in the developer console that the command
console.log(`tryin to redirect to ${callbackUrl}`);
is performed. But the page keeps showing the signIn-Page.
英文:
After a successful login on my custom signIn-Page, I use with next-auth, I'm trying to redirect back to the callbackUrl, but that doesn't work.
I'm using react 18.2.0, next 13.4.8-canary.2 and next-auth 4.22.1.
signIn-Page (\src\app\api\auth\signin\page.js):
"use client";
import { signIn } from "next-auth/react";
import { useSearchParams, useRouter } from "next/navigation";
import { useState } from "react";
export default function LoginPage() {
const router = useRouter();
const callbackUrl = useSearchParams().get("callbackUrl") || "/";
const course = callbackUrl.split("/").pop();
let [loading, setLoading] = useState(false);
let [password, setPassword] = useState("");
const [error, setError] = useState("");
async function onSubmit(event) {
event.preventDefault();
try {
setLoading(true);
const res = await signIn("credentials", {
redirect: false,
courseName: course,
password: password,
callbackUrl
});
if (!res?.error) {
setError("");
console.log(`tryin to redirect to ${callbackUrl}`);
router.push(callbackUrl);
} else {
setError("falsches Passwort");
}
setLoading(false);
} catch (error) {
setLoading(false);
setError(error);
}
}
function handleChange(event) {
event.preventDefault();
setPassword(event.target.value);
}
return (
<main style={{ display: "flex", justifyContent: "center" }}>
<div className="LoginContainer">
<br />
<div className="LoginBackgroundImage">
<h1 className="LoginHeading">Login</h1>
</div>
<form onSubmit={onSubmit}>
{error ? <strong className="w3-text-red">{error}</strong> : ""}
<div>
<p style={{ margin: 5 }}>
<strong>{course}</strong>
</p>
</div>
<div>
<input
className="passwordField"
required
type="password"
name="password"
value={password}
onChange={handleChange}
placeholder="Passwort"
/>
</div>
<button className="loginButton" type="submit" disabled={loading}>
{loading ? "lädt..." : "Anmelden"}
</button>
</form>
</div>
</main>
);
}
As you can see from the path, I'm using the new /app directory for routing. I know the login process is working because I can then call the callbackUrl manually in the browser and the content that requires authorization is displayed. I can also see in the developer console that the command
> console.log(`tryin to redirect to ${callbackUrl}`);
is performed. But the page keeps showing the signIn-Page.
答案1
得分: 0
我认为,我找到了原因。使用useRouter().push()跳转到的目标页面本身重定向到了登录页面。只有在您未登录为正确用户时,才应执行此重定向。由于重定向已经执行了一次以到达登录页面,尽管之后正确的用户已登录,但可能再次执行了重定向。造成这种情况的原因可能是目标页面是一个服务器页面,在登录后不会再次渲染。我现在通过直接链接到登录页面而不先访问目标页面来解决了这个问题,只有在登录后才首次访问目标页面。
英文:
I think, I found the reason. The target-page to which I useRouter().push() had a redirect itself to the loginpage. This redirect should only be executed if you are not logged in as the correct user. Since the redirect was already executed once to get to the login page, it was probably executed again afterwards, although the correct user was then logged in. The reason for this could be that the target-page is a server-page which is not rendered again after login. I have now solved this by linking directly to the login-page without calling up the target-page first and only after login is the target-page called up for the first time.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论