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

React Bootstrap Modal打开报classList相关TypeError错误如何解决

问题根源排查

报错是Bootstrap模态框的JS逻辑找不到目标DOM节点,尝试操作不存在节点的classList属性触发的,具体错误点如下:

  • 触发按钮的data-bs-target属性缺少ID选择器前缀#,Bootstrap无法定位到对应模态框节点
  • React中DOM类名属性不能写class,必须写className,否则类名无法正确挂载到DOM上,会导致Bootstrap操作节点异常
  • useAuthState返回值为数组格式,你直接当成user对象取email会导致初始加载时属性读取报错
  • 两个条件分支返回的模态框使用了重复的id="exampleModal",会导致选择器冲突
  • React中表单的for属性要写为htmlFor、tabindex要写为tabIndex,属性名不规范也会引发DOM属性异常

具体修改方案

1. 修改触发按钮代码

给data-bs-target的值加上#前缀,同时替换class为className:

<button type="button" className="btn btn-link nav-link active" data-bs-toggle="modal" data-bs-target="#exampleModal">
    Submit Fact
</button>

2. 修正Modal组件的属性与逻辑

import React from 'react';
import firebase from 'firebase/app';
import 'firebase/firestore';
import 'firebase/auth';
import 'firebase/analytics';
import { useAuthState } from 'react-firebase-hooks/auth';
import axios from 'axios';
import { useState } from 'react';
import SignIn from './SignIn'

const auth = firebase.auth();

function Modal() {
    // 修正useAuthState取值逻辑,返回值为[user, loading, error]数组
    const [user, loading] = useAuthState(auth);
    // 可选链读取email避免user为空时报错
    const Email = user?.email;
    const [Fact, setFact] = useState('');
    const [Source, setSource] = useState('');

    const handelSubmit = (e) => {
        e.preventDefault();
        const newFact = {Email, Fact, Source};
        axios({
            method: 'post',
            url: 'https://exampleapi.com/create',
            data: {
                "fact": {newFact}
            },
            headers: {
                'Content-Type': 'application/json',
            },
        }).then(function (response) {
            console.log(response);
        }).catch(function (error) {
            console.log(error);
        });
    }

    // 加载状态下不渲染模态框,避免节点未初始化引发报错
    if(loading) return null;

    // 抽离公共模态框外层,避免重复ID冲突,所有class替换为className
    return (
        <div className="modal fade" id="exampleModal" tabIndex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
            <div className="modal-dialog">
                <div className="modal-content">
                <div className="modal-header">
                    <h5 className="modal-title" id="exampleModalLabel">{user ? 'Add a Fact' : 'Sign in'}</h5>
                    <button type="button" className="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div className="modal-body">
                    {user ? (
                        <form onSubmit={handelSubmit}>
                            <div className="mb-3">
                                <label htmlFor="InputFact" className="form-label">Fact</label>
                                <input type="text" className="form-control" id="InputFact" aria-describedby="emailHelp" placeholder="enter your fact..." value={Fact} onChange={(e) => setFact(e.target.value)} required />
                            </div>
                            <div className="mb-3">
                                <label htmlFor="InputSource" className="form-label">Source</label>
                                <input type="url" className="form-control" id="InputSource" aria-describedby="emailHelp" placeholder="enter your source..." value={Source} onChange={(e) => setSource(e.target.value)} required />
                            </div>
                            <div className="modal-footer">
                                <button className="btn btn-outline-dark">Submit</button>
                            </div>
                        </form>
                    ) : (
                        <SignIn className="btn btn-outline-dark" message="Sign in with Google" />
                    )}
                </div>
                </div>
            </div>
        </div>
    )
}

export default Modal

内容的提问来源于stack exchange,提问作者Cool cow facts

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 01:39:02