React触发模态框报错Cannot read property 'classList' of undefined咨询
问题原因
你遇到的报错类型错误:无法读取未定义的属性'classList'核心是Bootstrap原生模态框触发逻辑和React状态更新/渲染时序不匹配,具体有两个直接诱因:
- 触发时序冲突:你点击按钮时同时执行两个操作:一是靠
data-bs-toggle触发原生Bootstrap模态框打开,二是dispatch更新store里的报价单ID。原生JS的事件触发优先级远高于React的状态更新、重渲染流程,此时你设置的条件渲染的模态框还没挂载到DOM上,Bootstrap JS找不到data-bs-target指定的DOM元素,操作不存在元素的classList就触发了报错。 - ID不匹配:按钮上的
data-bs-target是#modal-pdf-开头的动态值,但模态框的ID绑定的是modalTitle这个空state,你全程没有给modalTitle赋值,就算模态框完成渲染,ID也对应不上,Bootstrap仍然找不到目标元素。
解决方案
推荐优先用React状态控制模态框显示,完全避开原生Bootstrap的自动触发逻辑,适配性最高:
步骤1:移除原生触发属性
删除按钮上的data-bs-toggle和data-bs-target属性,不再依赖原生Bootstrap的自动模态框触发逻辑,修改后按钮代码:
<button type="button" onClick={() => { dispatch(sendEstimateToShow(estimate.id)) setShowModal(true) // 这里可以同步给modalTitle赋值,保证后续如果需要用ID的话和按钮生成规则一致 setModalTitle(`modal-pdf-${estimate.estimate_name.toLowerCase().replaceAll(' ', '-').replaceAll('°', '-')}`) }} className="btn btn-primary"> <i className="bi bi-eye-fill"></i> </button>
步骤2:新增状态控制模态框显示
在组件内新增控制模态框显示的状态:
const [showModal, setShowModal] = useState(false)
步骤3:调整模态框渲染逻辑
修改模态框的渲染条件和样式,用React状态控制显隐:
const estimateToShow = useSelector(state => state.estimatesReducer.estimateToShow) const estimateToShowData = estimates.filter(estimate => estimate.id === estimateToShow) {showModal && !isEmpty(estimateToShowData) && ( // 显示时加上show和d-block类,符合Bootstrap模态框显示的样式要求 <div className="modal show d-block" id={modalTitle} tabIndex="-1" aria-hidden={!showModal}> <div className="modal-dialog modal-dialog-centered modal-lg"> <div className="modal-content"> <div className="modal-header"> <h5 className="modal-title" id="exampleModalLabel">{estimateToShowData[0].estimate_name}</h5> <button type="button" className="btn-close" onClick={() => { setLoadPdf(false) setShowModal(false) // 可选:关闭时清空store里的报价单ID,避免残留 dispatch(sendEstimateToShow(null)) }} aria-label="Close"></button> </div> <div className="modal-body d-flex justify-content-center flex-column"> { loadPdf && ( <PDFViewer height={"500px"}> <EstimateTemplatePdf currentEstimate={estimateToShowData[0]}/> </PDFViewer> ) } </div> <div className="modal-footer"> <button type="button" onClick={() => { setLoadPdf(false) setShowModal(false) dispatch(sendEstimateToShow(null)) }} className="btn btn-secondary">关闭 </button> <a href={instance.url} className={"btn btn-primary"} download="devis.pdf"> 下载报价单 </a> </div> </div> </div> </div> )} // 可选:加上模态框蒙层 {showModal && <div className="modal-backdrop show"></div>}
替代方案(坚持用原生Bootstrap触发)
如果不想改动原生触发逻辑,按以下步骤调整:
- 移除模态框的条件渲染,一直渲染模态框DOM,没有数据时内容显示加载态即可,保证DOM初始就存在
- 提前给
modalTitle赋值,保证和按钮的data-bs-target生成规则完全一致 - 用useEffect监听
estimateToShow变化,拿到数据后再手动调用Bootstrap模态框实例的show方法触发显示
内容的提问来源于stack exchange,提问作者Atl31
相关产品推荐
相关产品推荐

