You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

属性更新时销毁并重新初始化Swiper实例报错问题排查

问题

在开发Gutenberg滑块区块时,使用以下代码初始化Swiper:

const containerRef = useRef(null);
const swiperRef = useRef(null);
const {
    attributes: { images, fx, auto },
    setAttributes,
} = props;

useEffect(() => {
    if (swiperRef.current) {
        console.log(swiperRef.current);
        // Destroy Swiper instance when updating.
        swiperRef.current.destroy(true, true);
    }
    // Init Swiper instance.
    swiperRef.current = new Swiper(containerRef.current, {
        modules: [Autoplay, Navigation, EffectFade],
        loop: true,
        effect: fx,
        fadeEffect: {
            crossFade: true
        },
        centeredSlides: false,
        autoHeight: false,
        observer: true,
        autoplay: auto ? {
            delay: 3000,
            disableOnInteraction: false,
            pauseOnMouseEnter: true,
        } : false,
        navigation: {
            nextEl: '.slider-navigation .slider-next',
            prevEl: '.slider-navigation .slider-prev',
        }
    });
}, [images, fx, auto]);

每当依赖数组中的属性变化时,useEffect钩子会执行。虽然已经在销毁实例前检查了swiperRef.current是否存在,但首次运行时(还未完成Swiper初始化),该条件为true,调用swiperRef.current.destroy(true, true)抛出错误:

Uncaught TypeError: r is null
    R http://example.com/wp-content/plugins/my-slider/build/blocks/slider/index.js?ver=20f7ca98c8222f0d1ea3:1
    detachEvents http://example.com/wp-content/plugins/my-slider/build/blocks/slider/index.js?ver=20f7ca98c8222f0d1ea3:1
    destroy http://example.com/wp-content/plugins/my-slider/build/blocks/slider/index.js?ver=20f7ca98c8222f0d1ea3:1
    edit http://example.com/wp-content/plugins/my-slider/build/blocks/slider/index.js?ver=20f7ca98c8222f0d1ea3:1
    commitHookEffectListMount http://example.com/wp-includes/js/dist/vendor/react-dom.js?ver=18.2.0:23160
    commitPassiveMountOnFiber http://example.com/wp-includes/js/dist/vendor/react-dom.js?ver=18.2.0:24936
    commitPassiveMountEffects_complete http://example.com/wp-includes/js/dist/vendor/react-dom.js?ver=18.2.0:24901

console.log(swiperRef.current)显示存在Swiper实例但未初始化,请问如何判断这种情况,避免首次运行时调用destroy方法?

解决方法

可以通过两种方式判断Swiper实例是否已完成初始化,从而避免首次执行时调用destroy:

方法1:检查实例的initialized属性

Swiper实例初始化完成后会自动添加initialized属性,值为true。修改判断条件,只有当实例存在且已初始化时才执行销毁:

if (swiperRef.current && swiperRef.current.initialized) {
    swiperRef.current.destroy(true, true);
}

方法2:使用额外的状态标记初始化状态

在组件中添加一个状态变量,标记是否已经完成过一次Swiper初始化,首次执行时跳过销毁逻辑:

const [isSwiperInitialized, setIsSwiperInitialized] = useState(false);

useEffect(() => {
    if (isSwiperInitialized && swiperRef.current) {
        swiperRef.current.destroy(true, true);
    }
    swiperRef.current = new Swiper(containerRef.current, {
        // 原有配置项保持不变
    });
    // 初始化完成后更新状态标记
    setIsSwiperInitialized(true);
}, [images, fx, auto]);

额外注意事项

  • 可以在useEffect开头添加if (!containerRef.current) return;,确保DOM容器挂载后再初始化Swiper,避免无效实例创建。
  • 确认Swiper的依赖模块(如Autoplay、Navigation)已正确导入,防止初始化异常。

内容的提问来源于stack exchange,提问作者leemon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 19:37:44