好吧,我试图创建一个 nextjs 项目,在数据库出现一些问题后,我连接到了 vercell 托管的项目。实际上,我确实使用了一些路由来将一些信息插入或选择到数据库中,因此我尝试使用这些新信息来进一步开发我的应用程序。我想添加一个动态反应组件,仅当登录的用户名保存在本地存储中时才会出现。经过一番研究,我确实找到了一个选项,但本地存储不保存数据,我不知道为什么。
好吧,我尝试过: 从路由组件使用不同的方法将数据保存在本地存储中,但它确实说本地存储未定义,所以我尝试了以下选项: 这是route.js代码:
import { NextResponse } from "next/server";
import { sql } from "@vercel/postgres";
export async function POST(req) {
const body = await req.json();
const { username, password } = body;
const resultat=await sql'SELECT * FROM Users WHERE username=${username}
AND passwordhash=${password}'
if(resultat.rows.length===0){
console.log("Authentification failed");
return NextResponse.json({ error:"Invalid credentials" }, { status: 404 });
}
if(username==resultat.rows[0].username &&
password==resultat.rows[0].passwordhash){
console.log("Merge autentificarea")
try{
localStorage.setItem("username",username) || ""
localStorage.setItem("password",password) || ""
console.log("Am salvat datele");}
catch (error){ }
return NextResponse.json({ message: "Logged In" },{ status:200 });
}
return NextResponse.json({ error:"Invalid credentials" }, { status: 404 });
}
但是控制台并没有返回。然后在使用使用该路线的页面时:
"use client"
import './LoginForm.css';
import Button from '../Button';
import { useState } from 'react';
import Link from 'next/link';
const LoginForm = () => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const onClickHandle = async () => {
console.log('Username:', username);
let res=await fetch("http://localhost:3000/api/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ username, password }),
});
let data=await res.json();
if(data.status === 200) {
localStorage.setItem("auth", true);
localStorage.setItem("username", username);
console.log(username)
router.push('/');
}
else{
console.error("Login failed",data.error)
}
}
return (
<div className="login-container">
<form className="login-form">
<h2>Login</h2>
<div className="form-group">
<label htmlFor="username">Username:</label>
<input
type="text"
id="username"
onChange={(e) => setUsername(e.target.value)}
required
/>
</div>
<div className="form-group">
<label htmlFor="password">Password:</label>
<input
type="password"
id="password"
onChange={(e) => setPassword(e.target.value)}
required
/>
</div>
<div>
<Link href="/"><Button onClick={onClickHandle}>Log In</Button></Link>
</div>
</form>
</div>
);
};
export default LoginForm;
然后在组件中我希望使用用户名:
"use client"
import React from 'react';
import "./Navbar.css"
import Button from './Button';
import Link from 'next/link';
import { useState,useEffect } from 'react';
export default function Navbar(){
const [username,setUsername]=useState("");
useEffect(()=>{
if(typeof window!=="undefined"){
if(localStorage.getItem("username")===null)
{
console.log("there is nothing here")
}
const auth = localStorage.getItem("auth");
if(auth){
const storedUserName = localStorage.getItem("username");
setUsername(storedUserName);
}
}
},[])
return (
<nav className="navbar">
<div className="container">
<ul className="nav-links">
<li>
<Link href="/">
<Button>Home</Button>
</Link>
</li>
</ul>
</div>
<div>
<Link href='/categories'><Button>Categorii</Button></Link>
</div>
<div>
<Link href="/newreleases"><Button>New Releases</Button></Link>
</div>
<div>
<Link href='/search'><Button>Search</Button></Link>
</div>
<div>
<Link href='/login'><Button>Log In</Button></Link>
</div>
{ username &&(
<div>
<Link href='/'><Button>{username}</Button></Link>
</div>
)}
</nav>
)
}
我真的不知道如何通过其他方式传递信息。
有两件事:
附注:不要将客户的密码存储在数据库以外的任何地方,即使这样也应该对其进行加密。 不要从 API 响应中返回它,并且绝对不要将其写入本地存储。
相反,您应该从 API 端点返回响应,并使用 that 响应在组件中设置本地存储。 像这样的东西:
// in API route, success case:
return NextResponse.json({ auth: true, username}, {status: 200});
顺便说一句,设置 localstorage 不会使导航栏组件中的
useEffect
运行,因此即使您获得在 localstorage 中设置的用户名,该组件也不会显示它。 您需要将用户名(或身份验证状态)作为道具传递给导航栏。 但这值得单独提出一个问题。