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

React注册登录组件卡在ReactLoading界面,Firebase问题求助

注册/登录卡在加载界面的问题排查与修复

核心问题拆解

  1. 异步逻辑混乱:用await获取createUserWithEmailAndPassword结果后又调用.then(),导致代码执行流程混乱,错误无法被有效捕获。
  2. 加载状态未重置:认证或Firestore操作失败时,isLoading没有设回false,加载动画一直停留在界面上。
  3. 错误捕获范围不全:try/catch只覆盖了认证步骤,Firestore的操作错误完全没被处理,既不提示用户也不重置状态。
  4. 安全隐患:直接把明文密码存到Firestore,Firebase Auth已经存储了密码哈希,完全没必要重复存储明文。
  5. API混用冲突:同时使用Firebase模块化API(getAuth)和旧版命名空间API(firebase.firestore()),可能导致初始化异常。

修复方案

  • 统一用Firebase v9+的模块化API,避免新旧API混用
  • 重构异步逻辑,全部用await处理,去掉冗余的.then()嵌套
  • 扩大错误捕获范围,所有异步操作的错误都要处理,同时重置加载状态
  • 删除Firestore中的明文密码字段
  • 用React状态管理错误提示,避免直接操作DOM

修复后的完整代码

import React from 'react';
import { Card } from 'react-bootstrap';
import { Link } from 'react-router-dom';
import Grid from '@material-ui/core/Grid';
import LoginString from '../../loginstrings';
import TextField from '@material-ui/core/TextField';
import ReactLoading from 'react-loading';
import { createUserWithEmailAndPassword, getAuth } from 'firebase/auth';
import { getFirestore, addDoc, collection } from 'firebase/firestore';

class SignUp extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            isLoading: false,
            email: "",
            password: "",
            name: "",
            errorMessage: "" // 用状态管理错误提示
        }
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
    }

    handleChange(event) {
        this.setState({
            [event.target.name]: event.target.value,
            errorMessage: "" // 输入时清空错误提示
        });
    }

    async handleSubmit(event) {
        const { name, password, email } = this.state;
        event.preventDefault();
        this.setState({ isLoading: true, errorMessage: "" });

        try {
            // 完成用户认证
            const auth = getAuth();
            const userCredential = await createUserWithEmailAndPassword(auth, email, password);
            const user = userCredential.user;

            // 写入Firestore用户集合(不存储密码)
            const db = getFirestore();
            const docRef = await addDoc(collection(db, 'users'), {
                name,
                id: user.uid,
                email,
                URL: '',
                description: ''
            });

            // 存储用户信息到本地
            localStorage.setItem(LoginString.FirebaseDocumentId, docRef.id);
            localStorage.setItem(LoginString.ID, user.uid);
            localStorage.setItem(LoginString.name, name);
            localStorage.setItem(LoginString.email, email);
            localStorage.setItem(LoginString.PhotoURL, "");
            localStorage.setItem(LoginString.Description, "");

            // 重置状态并跳转
            this.setState({ isLoading: false });
            this.props.history.push('/chat');

        } catch (error) {
            // 统一处理所有错误,给出针对性提示
            let errorMsg = "注册失败,请检查网络或账号信息";
            if (error.code === 'auth/email-already-in-use') {
                errorMsg = "该邮箱已被注册";
            } else if (error.code === 'auth/weak-password') {
                errorMsg = "密码长度需至少6位";
            }
            this.setState({
                isLoading: false,
                errorMessage: errorMsg
            });
            console.error("注册错误:", error);
        }
    }

    render() {
        const paper = {
            display: 'flex',
            flexDirection: 'column',
            alignItems: 'center',
            paddingLeft: '10px',
            paddingRight: '10px',
            marginTop: '10px'
        }
        return (
            <Grid container component="main" className="root">
                <Grid item xs={1} sm={4} md={7} className="image">
                    <div className="leftimage">
                        {this.state.isLoading ? (
                            <div className="viewLoadingProfile">
                                <ReactLoading
                                    type={'spin'}
                                    color={'#203152'}
                                    height={'10%'}
                                    width={'10%'}
                                />
                            </div>
                        ) : null}
                    </div>
                </Grid>
                <Grid item xs={12} sm={8} md={5} className="loginrightcomponent" elevation={6}>
                    <Card style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', width: '100%', boxShadow: "0 5px 5px #808888" }}>
                        <Link to="/">
                            <button className="btnhome">
                                <i className="fa fa-home"><span>Go to Home</span></i>
                            </button>
                        </Link>
                    </Card>
                    <div style={paper}>
                        <form style={{ marginTop: '50px', width: '100%' }} noValidate onSubmit={this.handleSubmit}>
                            <TextField
                                variant="outlined"
                                margin="normal"
                                required
                                fullWidth
                                id="email"
                                label="Email Address"
                                name="email"
                                autoComplete="email"
                                autoFocus
                                onChange={this.handleChange}
                                value={this.state.email}
                            />
                            <TextField
                                variant="outlined"
                                margin="normal"
                                required
                                fullWidth
                                id="password"
                                label="Password:"
                                name="password"
                                type="password"
                                autoComplete="current-password"
                                onChange={this.handleChange}
                                value={this.state.password}
                            />
                            <TextField
                                variant="outlined"
                                margin="normal"
                                required
                                fullWidth
                                id="name"
                                label="Your Name"
                                name="name"
                                autoComplete="name"
                                onChange={this.handleChange}
                                value={this.state.name}
                            />
                            <div>
                                <p style={{ color: 'grey', fontSize: '15px' }}>Please fill all fields and password should be greater than 6</p>
                            </div>
                            <div className="CenterAliningItems">
                                <button className="button1" type="submit">
                                    Signup
                                </button>
                            </div>
                            {this.state.errorMessage && (
                                <div>
                                    <p style={{ color: 'red' }}>{this.state.errorMessage}</p>
                                </div>
                            )}
                        </form>
                    </div>
                </Grid>
            </Grid>
        );
    };
};
export default SignUp;

额外检查项

  1. 确认项目入口文件已正确初始化Firebase(调用initializeApp)
  2. 检查Firestore规则:开发环境可临时设置为allow read, write: if true;,生产环境必须配置严格的安全规则
  3. 登录组件可参照同样逻辑修复:统一用await处理异步操作,确保错误时重置加载状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 14:10:37