enter image description here It is my Auth Login form. I have AuthContext. Let's try log in.

enter image description here I've clicked "log in" button. And we see AuthContext "user" : underfind

enter image description here Then click reload page, and here we go, we have logged in

为什么会是这样呢?

登录.js

import React, {useState} from 'react'
import {useLogin} from '../hooks/useLogin'
import { useNavigate } from 'react-router-dom'

const Login = () => {
    const [email, setEmail] = useState('')
    const [password, setPassword] = useState('')
    const {login, error, isLoading} = useLogin()

    let navigate = useNavigate()

    const handleSubmit = async (e) => {
        e.preventDefault()

        await login(email, password)
        
    }
    return(
        <div className='container'>
            <h1>
                login page
            </h1>
            <form className={'d-flex flex-column'} onSubmit={handleSubmit}>
            <h3>Log in</h3>
            <label>Email:</label>
            <input
                type={'email'}
                onChange={(e) => setEmail(e.target.value)}
            />
            <label>Password</label>
            <input
                type={'password'}
                onChange={(e) => setPassword(e.target.value)}
            />
            <button disabled={isLoading} type={'submit'}>
                Log in
            </button>
            {error && <div className={'error'}>
                            {error}
                        </div>}
        </form>
        </div>
    )
}

export default Login;

use登录.js

import { useState } from "react";
import { useAuthContext } from "./useAuthContext";


export const useLogin = () => {
    const [error, setError] = useState(null)
    const [isLoading, setIsLoading] = useState(null)
    const {dispatch} = useAuthContext()

    const login = async (email, password) => {
        setIsLoading(true)
        setError(null)

        const response = await fetch('/api/user/login', {
            method:'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({email, password})

        })

        const json = await response.json()

        if(!response.ok){
            setIsLoading(false) 
            setError(json.error)

        }
        
        if(response.ok){
            localStorage.setItem('user', JSON.stringify(json))
            dispatch({type:'LOGIN', paylaod:json})
            setIsLoading(false)
        }
    }

    return {login, isLoading, error}
}

AuthContext.js

import { createContext, useReducer, useEffect } from "react";

export const AuthContext = createContext()

export const authReducer = (state, action) => {
    switch(action.type){
        case 'LOGIN':
            return {user: action.payload}
        case 'LOGOUT':
            return {user:null}
        default:
            return state
    }
}

export const AuthContextProvider = ({children}) => {
    const [state, dispatch] = useReducer(authReducer, {
        user:null
    })

    useEffect(() => {
        const user = JSON.parse(localStorage.getItem('user'))

        if(user){
            dispatch({type:'LOGIN', payload: user})
        }
    }, [])

    console.log('AuthContext state', state)

    return(
        <AuthContext.Provider value={{...state, dispatch}}>
            {children}
        </AuthContext.Provider>
    )
}

UseAuthContext.js

import { AuthContext } from "../context/AuthContext";
import { useContext } from "react";

export const useAuthContext = () => {
    const context = useContext(AuthContext)

    if(!context){
        throw Error('useAuthContext must be used inside an AuthContextProvider')
    }

    return context
}

以下是Navbar.js

import React from "react";
import { useAuthContext } from "../hooks/useAuthContext";
import { useLogout } from "../hooks/useLogout";
import { Link } from "react-router-dom";


const Nav = () => {

    const {logout} = useLogout()
    const {user} = useAuthContext()
    const handleClick= () => {
        logout()
    }

    return(
        <div>

            {user && (
                    <div className="bg-dark text-light align-item-center d-flex justify-content-between m-auto container-fluid p-2">
                        <span className="m-0 p-0 d-flex align-item-center">{user.email}</span>
                        <button className="btn btn-outline-danger" onClick={handleClick}>logout</button>
                    </div>
            )}

                {!user && (
                    <div className="d-flex justify-content-between">

                        <Link to='/'>
                            <button>HOME</button>
                        </Link>
                        <Link to='/login'>
                            <button>LOGIN</button>
                        </Link>
                        <Link to='/signup'>
                            <button>SIGNUP</button>
                        </Link>
                    </div>
                )}
</div>
    )
}

export default Nav

Index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { AuthContextProvider } from './context/AuthContext';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <AuthContextProvider>
      <App />
    </AuthContextProvider>
  </React.StrictMode>
);

App.js

import {BrowserRouter, Routes, Route} from 'react-router-dom'
import Nav from './components/Nav';
import Home from './pages/home';
import Login from './pages/login';
import Signup from './pages/signup';

function App() {
  return (
    <div>
        <BrowserRouter>
          <Nav/>
            <Routes>
              <Route path={'/'} element={<Home/>}/>
              <Route path={'/login'} element={<Login/>}/>
              <Route path={'/signup'} element={<Signup/>}/>
            </Routes> 
        </BrowserRouter>
    </div>
  );
}

export default App;

我不认为这是服务器错误.

推荐答案

useLogin个有效载荷中有一个拼写错误

dispatch({type:'LOGIN', paylaod:json});

// Should be: Payload
dispatch({type:'LOGIN', payload:json});

Javascript相关问答推荐

React Hooks中useState的同步问题

禁用从vue.js 2中的循环创建的表的最后td的按钮

React:未调用useState变量在调试器的事件处理程序中不可用

拖放仅通过 Select 上传

如何从一个列表中创建一个2列的表?

在拖放时阻止文件打开

使用LocaleCompare()进行排序时,首先使用大写字母

无法从NextJS组件传递函数作为参数'

JSDoc创建并从另一个文件导入类型

还原器未正确更新状态

Use Location位置成员在HashRouter内为空

按什么顺序接收`storage`事件?

如何根据输入数量正确显示alert ?

如何在Jest中模拟函数

为什么NULL不能在构造函数的.Prototype中工作

由于http.get,*ngIf的延迟很大

Reaction-在同一页内滚动导航(下拉菜单)

如何格式化API的响应

单击时同时 Select 和展开可访问的行

调试jQuery代码以获取所有行的总和(票证类型)