React useState钩子异常:调用setActiveSlide后Swiper实例story变为null
为什么调用setActiveSlide后Swiper实例story会变成null?
这个问题我之前也碰到过,核心原因是你用普通变量story保存Swiper实例,而React组件重渲染时会重置这个变量。
当你调用setActiveSlide更新组件状态activeSlide时,React会触发组件的重新渲染——整个Slideshow组件函数会再次执行一遍。这时候你写的var story = null;会重新运行,直接把之前已经创建好的Swiper实例覆盖成了null,所以后续点击「上一张」「下一张」按钮时,调用story.slidePrev()自然就会抛出Cannot read property 'slideNext' of null的错误。
要解决这个问题,你需要用React的useRef来保存Swiper实例,因为useRef创建的引用对象在组件的整个生命周期内都会保持稳定,不会因为组件重渲染而被重置。
下面是修改后的完整代码:
import React, { useState, useEffect, useRef } from "react"; import Swiper from "swiper"; const Slideshow = props => { const swiper = useRef(); // 用useRef保存Swiper实例,替代普通变量 const story = useRef(null); const [activeSlide, setActiveSlide] = useState(""); useEffect(() => { // 将实例赋值给story.current story.current = new Swiper(swiper.current, { loop: false, speed: 1100 }); }, []); const prevSlide = () => { setActiveSlide("PREV"); // 通过current属性访问持久化的实例 story.current.slidePrev(); }; const nextSlide = () => { setActiveSlide("NEXT"); story.current.slideNext(); }; return ( <div className="container-story" ref={swiper}> <div className="container-story-wrapper swiper-wrapper"> {props.children} </div> <div className="navigation"> <button onClick={prevSlide}> Previous </button> <button onClick={nextSlide}> Next </button> {activeSlide} </div> <div className="lightbox-container"></div> </div> ); }; export default Slideshow;
简单梳理下关键修改点:
- 把
var story = null;替换为const story = useRef(null);,用useRef创建一个跨渲染周期的持久化引用 - 在
useEffect初始化逻辑中,将Swiper实例赋值给story.current - 在按钮点击函数里,通过
story.current调用Swiper的滑动方法
这样无论组件因为状态更新重渲染多少次,story.current都会保留住之前创建的Swiper实例,不会再出现null的问题了。
内容的提问来源于stack exchange,提问作者Gunther von Goetzen Sanchez
相关产品推荐
相关产品推荐

