升级NodeJS至16.13.0后MaterializeCSS轮播方法next、set报错怎么解决?
报错触发原因
- 传参类型错误:
document.querySelectorAll('.carousel')返回的是符合选择器的所有DOM元素组成的NodeList集合,而M.Carousel.getInstance方法要求传入单个DOM元素作为参数,传入集合只会返回undefined,调用undefined的set、next方法自然会抛出类型错误。 - 事件监听时机错误:React函数组件内直接绑定
DOMContentLoaded事件逻辑不可靠,升级Node版本后配套的构建工具(如webpack、react-scripts)编译逻辑、资源加载顺序发生变化,组件挂载时DOMContentLoaded事件大概率已经触发完毕,你写的初始化逻辑根本不会按预期执行,轮播没有正确初始化也会导致实例获取失败。 - 缺少副作用清理逻辑:定时器设置后没有在组件卸载时清除,组件销毁后定时器仍然会执行,除了报错还会造成内存泄漏。
修复方案
修改逻辑如下:
- 用React官方提供的
useEffect钩子代替DOMContentLoaded监听,保证组件挂载完成、DOM渲染完毕后再执行轮播初始化逻辑 - 改用
document.querySelector直接获取单个轮播DOM元素,或者从querySelectorAll返回的集合中取出对应下标的单个元素再传入实例方法 - 直接存储初始化得到的轮播实例,避免重复调用
getInstance,同时添加副作用清理逻辑清除定时器
修改后的完整代码:
import '../css/successAnimate.css' import M from 'materialize-css'; import { useEffect } from 'react'; const HomeContents = () => { useEffect(() => { // 直接获取单个轮播元素 const elemCarousel = document.querySelector('.carousel'); // 初始化并拿到实例 const carouselInstance = M.Carousel.init(elemCarousel); // 直接用实例调用方法 carouselInstance.set(2); const timer = window.setInterval(() => { carouselInstance.next(); }, 2000); // 组件卸载时清除定时器、销毁轮播实例 return () => { clearInterval(timer); carouselInstance.destroy(); } }, []); // 空依赖数组保证只在组件挂载时执行一次 return ( <div className="contents"> {/* --==== 客户评价 ====-- */} <section id="customer-testimonials" className="mid-sec2"> <div className="row"> <div className="container"> <div className="customer-sect-title"> <h3 className="sect-title">客户评价</h3> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p> </div> <div className="carousel testimony-wrapper visible-xs"> <div className="testimony-block carousel-item"> <div className="flex-div review-title"> <img src={require("../images/rp-1.svg").default} alt="points" className="rti-1" /> <span className="bold">Lorem ipsum dolor</span> </div> <div className="review-container"> <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. </p> </div> <div className="reviewer-details"> <div className="reviewer-name"> <b>Christiana</b> </div> </div> </div> <div className="testimony-block carousel-item"> <div className="flex-div review-title"> <img src={require("../images/rp-1.svg").default} alt="points" className="rti-1" /> <span className="bold">Torem ipsum dolort</span> </div> <div className="review-container"> <p> Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </p> </div> <div className="reviewer-details"> <div className="reviewer-name"> <b>Abubakar</b> </div> </div> </div> <div className="testimony-block carousel-item"> <div className="flex-div review-title"> <img src={require("../images/rp-1.svg").default} alt="points" className="rti-1" /> <span className="bold">Cupidatat non proident</span> </div> <div className="review-container"> <p> Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. </p> </div> <div className="reviewer-details"> <div className="reviewer-name"> <b>Chinedu Nwaiwu</b> </div> </div> </div> </div> </div> </div> </section> {/* --==== 客户评价模块结束 ====-- */} </div> ); } export default HomeContents;
内容的提问来源于stack exchange,提问作者Mykel Eze
相关产品推荐
相关产品推荐

