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

React Web认证中setError无法显示错误信息的问题求助

问题:React认证应用提交不匹配密码时无错误提示

我跟着Web Dev Simplified的YouTube教程(约20分钟处)开发React Web认证应用,遇到一个异常:提交邮箱与不匹配的密码时,本应显示错误信息,但无法触发任何错误提示。尝试过初始化错误信息可正常显示,但后续调用setError无法更新错误内容,核对过命名一致性,已排查多日未解决。

相关代码如下:

./index.js

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './components/App';
import 'bootstrap/dist/css/bootstrap.min.css';

const root = ReactDOM.createRoot(document.getElementById('root'));

root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

./components/App.js

import React from "react";
import Signup from './Signup'
import { Container } from 'react-bootstrap'
import { AuthProvider } from '../contexts/AuthContext'

function App() {
  return (
    <AuthProvider>
      <Container className="d-flex align-items-center justify-content-center" style={{ minHeight: "100vh" }}>
        <div className="w-100" style={{ maxWidth: "400px" }}>
          <Signup />
        </div>
      </Container>
    </AuthProvider>
  )
}

export default App;

./contexts/AuthContext.js

import React, { useContext, useState, useEffect } from 'react'
import { auth } from '../firebase'

const AuthContext = React.createContext()

export function useAuth() {
    return useContext(AuthContext)
}

export function AuthProvider({ children }) {
    const [currentUser, setCurrentUser] = useState()

    function signup(email, password) {
        return auth.createUserWithEmailAndPassword(email, password)
    }

    useEffect(() => {
        const unsubscribe = auth.onAuthStateChanged(user => { 
            setCurrentUser(user)
        })
        return unsubscribe
    }, [])

    const value = { currentUser, signup }
    
    return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>
    
}

./components/Signup.js

import React, { useRef, useState } from 'react';
import { Form, Button, Card, Alert } from 'react-bootstrap';
import { useAuth } from '../contexts/AuthContext';

export default function Signup() {
    const emailRef = useRef();
    const passwordRef = useRef();
    const passwordConfirmRef = useRef();
    const { signup } = useAuth();
    const [error, setError] = useState("");
    const [loading, setLoading] = useState(false);

    async function handleSubmit(e) {
        e.preventDefault();

        if (passwordRef.current.value !== passwordConfirmRef.current.value) {
            return setError("Passwords do not match");
        }

        try {
            setError("");
            setLoading(true);
            await signup(emailRef.current.value, passwordRef.current.value);
        } catch {
            setError("Failed to create an account");
        }
        setLoading(false);
    }

    return (
        <>
            <Card>
                <Card.Body>
                    <h2 className="text-center mb-4">Sign Up</h2>
                    {error && <Alert variant="danger">{error}</Alert>}
                    <Form onSubmit={handleSubmit}>
                        <Form.Group id="email">
                            <Form.Label>Email</Form.Label>
                            <Form.Control type="email" ref={emailRef} required />
                        </Form.Group>
                        <Form.Group id="password">
                            <Form.Label>Password</Form.Label>
                            <Form.Control type="password" ref={passwordRef} required />
                        </Form.Group>
                        <Form.Group id="password-confirm">
                            <Form.Label>Password Confirmation</Form.Label>
                            <Form.Control type="password" ref={passwordConfirmRef} required />
                        </Form.Group>
                    </Form>
                    <Button disabled={loading} className="w-100" type="submit">
                        Sign Up
                    </Button>
                </Card.Body>
            </Card>
            <div className="w-100 text-center mt-2">
                Already have an account? Log In
            </div>
        </>
    );
}

解决方案

核心问题是提交按钮不在<Form>标签内部,导致表单的onSubmit事件未被触发,handleSubmit函数完全没执行,自然不会运行密码匹配检测、错误状态更新的逻辑。

修改./components/Signup.js,将<Button>移动到<Form>标签内部:

// 修改后的Signup.js返回部分
return (
    <>
        <Card>
            <Card.Body>
                <h2 className="text-center mb-4">Sign Up</h2>
                {error && <Alert variant="danger">{error}</Alert>}
                <Form onSubmit={handleSubmit}>
                    <Form.Group id="email">
                        <Form.Label>Email</Form.Label>
                        <Form.Control type="email" ref={emailRef} required />
                    </Form.Group>
                    <Form.Group id="password">
                        <Form.Label>Password</Form.Label>
                        <Form.Control type="password" ref={passwordRef} required />
                    </Form.Group>
                    <Form.Group id="password-confirm">
                        <Form.Label>Password Confirmation</Form.Label>
                        <Form.Control type="password" ref={passwordConfirmRef} required />
                    </Form.Group>
                    {/* 将按钮移入Form内部 */}
                    <Button disabled={loading} className="w-100 mt-3" type="submit">
                        Sign Up
                    </Button>
                </Form>
            </Card.Body>
        </Card>
        <div className="w-100 text-center mt-2">
            Already have an account? Log In
        </div>
    </>
);

原因说明

React Bootstrap的<Form>组件遵循HTML表单的常规逻辑:只有当提交按钮处于表单标签内部时,点击按钮才会触发表单的onSubmit事件,进而绑定的handleSubmit函数才会执行。之前按钮在Form外部,点击时只是普通按钮,不会触发表单提交逻辑,所以所有错误检测和状态更新的代码都没运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 05:30:45