使用React Hooks实现Bootstrap 5模态框报Cannot read 'show' of null错误
问题原因
你的代码核心错误有4个:
- React的
setState是异步更新的,同一渲染周期内调用setModal后,当前作用域下的modal变量还是初始的null值,不会立刻拿到更新后的Modal实例,因此调用modal.show()会直接报错。 - Bootstrap Modal的配置参数传错了位置,你把
{keyboard: false}作为setModal的第二个参数传入,没有任何作用,该配置应该作为第二个参数传给new Modal()构造函数。 useEffect依赖数组为空,后续props.json发生变化时不会重新触发逻辑,无法满足动态判断展示的需求。- 关闭按钮的回调没有做非空判断,Modal未初始化完成时点击关闭也会触发同类报错。
修复后的完整代码
import { Modal } from 'bootstrap'; import React, { useState, useEffect, useRef } from 'react'; import ParseExceptions from './ParseExceptions'; const ParseExceptionsModal = (props) => { // 用ref存Modal实例,不需要响应式更新,更适合存储第三方实例 const modalRef = useRef(null); const parseExceptionModal = useRef(); // 依赖添加props.json,json变化时重新触发逻辑 useEffect(() => { // 仅初始化一次Modal实例 if (!modalRef.current) { modalRef.current = new Modal(parseExceptionModal.current, { keyboard: false, }); } // 满足条件直接调用show,不需要等state更新 if (props.json.length > 0) { modalRef.current.show(); } }, [props.json]); // 关闭逻辑封装,加非空判断 const handleClose = () => { if (modalRef.current) { modalRef.current.hide(); } }; return ( <> <div className="modal fade" tabIndex="-1" role="dialog" ref={parseExceptionModal} aria-labelledby="parseExceptionModal" aria-hidden="true"> <div className="modal-dialog" role="document"> <div className="modal-content"> <div className="modal-header"> <h5 className="modal-title">{props.title}</h5> <button type="button" className="btn-close" onClick={handleClose} aria-label="Close"> </button> </div> <div className="modal-body"> <ParseExceptions json={props.json} /> </div> <div className="modal-footer"> <button onClick={handleClose} type="button" className="btn btn-outline-secondary"> Dismiss </button> </div> </div> </div> </div> </> ); }; export default ParseExceptionsModal;
核心修改说明
- 用
useRef存储Modal实例,不需要触发组件重新渲染,也避开了state异步更新的问题,实例初始化完成后可以直接调用方法。 - 修正了Modal配置的传递位置,把
{keyboard: false}传入Modal构造函数。 useEffect依赖数组添加props.json,后续json更新时可以重新判断是否需要展示模态框。- 封装关闭逻辑,增加非空判断,避免未初始化时调用方法报错。
内容的提问来源于stack exchange,提问作者domshyra
相关产品推荐
相关产品推荐

