You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js路由向组件传值及LocalStorage存储失败问题求助

Next.js登录后LocalStorage存值失败及Navbar动态显示问题解决

问题分析

  • API路由调用localStorage报错:API路由运行在服务器端,localStorage是浏览器专属API,服务器环境不存在该对象,因此报错,这部分代码完全无效,必须删除。
  • LoginForm存值后Navbar无法读取:
    1. 登录成功判断逻辑错误:你用data.status === 200判断,但后端返回的JSON中并没有status字段,应使用res.ok或res.status === 200。
    2. 未导入路由钩子:router.push('/')会报错,因为没引入Next.js的useRouter,导致登录后无法跳转,Navbar可能无法重新渲染。
    3. Navbar的useEffect仅执行一次:登录后跳转回首页时,Navbar已完成挂载,不会重新读取localStorage,状态无法更新。

修复代码示例

1. 修正API路由(移除localStorage相关代码)

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");
        return NextResponse.json({ message: "Logged In" }, { status: 200 });
    }
    
    return NextResponse.json({ error: "Invalid credentials" }, { status: 404 });
}

2. 修正LoginForm组件(修复路由与判断逻辑)

"use client"
import './LoginForm.css';
import Button from '../Button';
import { useState } from 'react';
import { useRouter } from 'next/navigation';

const LoginForm = () => {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const router = useRouter();

  const onClickHandle = async () => {
    const res = await fetch("/api/login", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ username, password }),
    });

    if (res.ok) {
      localStorage.setItem("auth", "true");
      localStorage.setItem("username", username);
      router.push('/');
    } else {
      const data = await res.json();
      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>
          <Button onClick={onClickHandle}>Log In</Button>
        </div>
      </form>
    </div>
  );
};

export default LoginForm;

注意:移除了Link包裹Button的写法,因为点击事件中已包含router.push,重复包裹会导致跳转异常。

3. 修正Navbar组件(监听localStorage变化)

"use client"
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(() => {
    const updateUsername = () => {
      if (typeof window !== "undefined") {
        const auth = localStorage.getItem("auth");
        setUsername(auth ? localStorage.getItem("username") || "" : "");
      }
    };

    updateUsername();
    // 监听localStorage变化,同步更新状态
    window.addEventListener('storage', updateUsername);

    return () => window.removeEventListener('storage', updateUsername);
  }, []);

  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>
      {!username ? (
        <div>   
          <Link href='/login'><Button>Log In</Button></Link>
        </div>
      ) : (
        <div>
          <Link href='/'><Button>{username}</Button></Link>
        </div>
      )}
    </nav>
  )
}

优化了登录状态显示逻辑,添加storage事件监听,确保其他页面修改localStorage时Navbar能同步更新。

其他可行的传值/状态管理方式

  • React Context:创建AuthContext,登录成功后更新Context中的用户信息,Navbar直接从Context读取,无需依赖localStorage,适合小型项目。
  • 轻量状态管理库(Zustand/Jotai):相比Context更简洁,无需层层包裹,组件可直接订阅状态,登录时更新状态后Navbar实时获取。
  • NextAuth.js:专业身份验证方案,支持Session管理,服务器端与客户端均可获取用户信息,安全性更高,适合需要完善身份验证的项目。
  • Cookie存储:API路由登录成功后设置HttpOnly Cookie存储用户信息,服务器端渲染时可直接读取Cookie,适合需要SSR显示用户信息的场景。

内容的提问来源于stack exchange,提问作者Riippeerreerr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 16:30:08