如何将值从 nextjs 路由传递到实际组件

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

好吧,我试图创建一个 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>
  )
}

我真的不知道如何通过其他方式传递信息。

javascript reactjs next.js local-storage
1个回答
0
投票

有两件事:

  1. 您尝试将数据库调用的响应保存在 API 路由中的本地存储中,该路由在 server 上运行,然后在组件中读取它,该组件在 client 浏览器上呈现,因此不会工作。
  2. 您从数据库获取用户名,但随后您不会将其作为 API 响应的一部分返回。

附注:不要将客户的密码存储在数据库以外的任何地方,即使这样也应该对其进行加密。 不要从 API 响应中返回它,并且绝对不要将其写入本地存储。

相反,您应该从 API 端点返回响应,并使用 that 响应在组件中设置本地存储。 像这样的东西:

// in API route, success case:
return NextResponse.json({ auth: true, username}, {status: 200});

顺便说一句,设置 localstorage 不会使导航栏组件中的

useEffect
运行,因此即使您获得在 localstorage 中设置的用户名,该组件也不会显示它。 您需要将用户名(或身份验证状态)作为道具传递给导航栏。 但这值得单独提出一个问题。

© www.soinside.com 2019 - 2024. All rights reserved.