React组件引入外部模态框JS文件报addEventListener空值错误求助
问题原因
- 外部JS执行时机错误:你引入的main.js会在导入时立即执行,此时Work组件的DOM还未渲染到页面中,
document.getElementById获取目标元素返回null,调用addEventListener时触发空值报错。 - 开发模式不符合React规范:React基于状态驱动视图更新,直接操作原生DOM、手动插入script标签的原生JS写法不适用于React开发场景。
修复方案
完全移除外部main.js的引入和组件末尾的script标签,通过React组件状态控制模态框的显隐,修改后的Work组件代码如下:
import React, { Component } from 'react'; import toDoListApp from '../mockups/to-do-list-img..jpg'; import pokeMockup from '../mockups/mockup-poke.jpg'; import ExpatColMock from '../img/colombia_logo.png'; import DogAPIMock from '../mockups/mockup-doggie.gif'; class Work extends Component { state = { showModal1: false, showModal2: false } // 控制第一个模态框 openModal1 = () => this.setState({showModal1: true}) closeModal1 = () => this.setState({showModal1: false}) handleClickOutside1 = (e) => { if(e.target.id === 'modal-background') this.closeModal1() } // 控制第二个模态框 openModal2 = () => this.setState({showModal2: true}) closeModal2 = () => this.setState({showModal2: false}) handleClickOutside2 = (e) => { if(e.target.id === 'modal-background2') this.closeModal2() } render() { return ( <> <section> <div> {/* 第一个模态框 */} <div className="mCustomScrollbar" data-mcs-theme="dark" id="modal-background" style={{display: this.state.showModal1 ? 'block' : 'none'}} onClick={this.handleClickOutside1} > <div id="modal"> <span id="close-btn" onClick={this.closeModal1}>×</span> <img className="modal-img" src="mockups/mockup.png" alt="expatcolombia" /> <h2 className="modal-title">Expat Colombia</h2> <div className="modal-text"> <h3>Description</h3> <p>Expat Service for people moving to Colombia. They provide consultations, tours, and assist in housing.</p> <h3>Dependencies</h3> <p>HTML, CSS, Javascript</p> </div> <div className="buttons"> <a href="https://drxl95.github.io/Colombia/" target="_blank" rel="noopener noreferrer">Visit</a> <a href="https://github.com/Drxl95/Colombia" target="_blank" rel="noopener noreferrer">Github</a> </div> </div> </div> {/* 第二个模态框 */} <div className="mCustomScrollbar2" data-mcs-theme="dark" id="modal-background2" style={{display: this.state.showModal2 ? 'block' : 'none'}} onClick={this.handleClickOutside2} > <div id="modal2"> <span id="close-btn2" onClick={this.closeModal2}>×</span> <img className="modal-img2" src="mockups/poke-mockup.jpg" alt="expatcolombia" /> <h2 className="modal-title">PokemonAPI</h2> <div className="modal-text2"> <h3>Description</h3> <p>Pokemon-themed App with a that includes names, images, and stats of different Pokemons.</p> <h3>Dependencies</h3> <p>Javascript, JQuery, Ajax</p> </div> <div className="buttons2"> <a href="poke_demo.html" target="_blank" rel="noopener noreferrer">Demo</a> <a href="https://github.com/Drxl95/PokemonAPI" target="_blank" rel="noopener noreferrer">Github</a> </div> </div> </div> </div> <div> <header className="ScriptHeader"> <div> <h1 className="work-title">My Work</h1> </div> </header> <section id="work"> {/* Image row 1 */} <div className="row"> <div className="column"> <div className="container"> <img src={toDoListApp} className="image" alt="to-do-list-api" /> <a href="https://github.com/Drxl95/To-Do-List" target="_blank" rel="noopener noreferrer"> <div className="overlay"> <div className="text">Simple jQuery To Do List App</div> </div> </a> </div> </div> <div className="column"> <a id="open-btn2" onClick={this.openModal2}> <div className="container"> <img src={pokeMockup} className="image" alt="PokemanAPI" /> <div className="overlay"> <div className="text">Pokemon-themed API app <br /></div> </div> </div> </a> </div> <div className="column"> <a id="open-btn" onClick={this.openModal1}> <div className="container"> <img src={ExpatColMock} className="image" alt="expatcolombia.com" /> <div className="overlay"> <div className="text">Expat Colombia</div> </div> </div> </a> </div> <div className="column"> <a href="https://github.com/Drxl95/DogAlbum" target="_blank" rel="noopener noreferrer"> <div className="container"> <img src={DogAPIMock} className="image" alt="dogAPI-mockup" /> <div className="overlay"> <div className="text">Dog Album API</div> </div> </div> </a> </div> </div> </section> </div> </section> </> ) } } export default Work
内容的提问来源于stack exchange,提问作者RDX10290
相关产品推荐
相关产品推荐

