当属性更新时销毁并重新初始化Swiper实例。

huangapple go评论70阅读模式
英文:

Destroy and reinit Swiper instance when an attribute is updated

问题

在第一次运行时,要检查Swiper实例是否已初始化,以避免调用swiperRef.current.destroy(true, true),可以添加一个条件来检查swiperRef.current是否存在且已初始化。您可以像这样修改代码:

useEffect(() => {
    if (swiperRef.current && swiperRef.current.initialized) { // 添加对initialized属性的检查
        console.log(swiperRef.current);
        // Destroy Swiper instance when updating.
        swiperRef.current.destroy(true, true);
    }
    // Init Swiper instance.
    if (!swiperRef.current) {
        swiperRef.current = new Swiper(containerRef.current, {
            // Swiper配置
        });
    }
}, [images, fx, auto]);

通过检查swiperRef.current是否存在且initialized属性为true,您可以确保只有在Swiper实例已经初始化的情况下才会执行销毁操作,从而避免在第一次运行时出现错误。

英文:

I'm using the following JS code in a Gutenberg block that displays a Swiper slider:

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]);

As you can see, every time one of the attributes in the dependencies array changes, the useEffect hook is run. Inside it I check for the existence of a Swiper instance before destroying it, but for some reason in the first run (no Swiper slider is present) the swiperRef.current conditional is true and the swiperRef.current.destroy(true, true) call throws an error:

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

The console.log(swiperRef.current) returns this:

{
"__swiper__": true,
"support": {
"smoothScroll": true,
"touch": false
},
"device": {
"ios": false,
"android": false
},
"browser": {
"isSafari": false,
"needPerspectiveFix": false,
"isWebView": false
},
"eventsListeners": {
"init": [
null,
null,
null,
null
],
"destroy": [
null,
null,
null,
null
],
"beforeTransitionStart": [
null
],
"sliderFirstMove": [
null
],
"touchEnd": [
null
],
"slideChange": [
null
],
"toEdge": [
null
],
"fromEdge": [
null
],
"lock": [
null
],
"unlock": [
null
],
"enable": [
null
],
"disable": [
null
],
"click": [
null
],
"beforeInit": [
null
],
"setTranslate": [
null
],
"setTransition": [
null
],
"transitionEnd": [
null
],
"virtualUpdate": [
null
]
},
"eventsAnyListeners": [],
"modules": [
null,
null,
null,
null,
null
],
"autoplay": {
"running": false,
"paused": false,
"timeLeft": 0
},
"navigation": {
"nextEl": null,
"prevEl": null
},
"params": {
"init": true,
"direction": "horizontal",
"oneWayMovement": false,
"touchEventsTarget": "wrapper",
"initialSlide": 0,
"speed": 300,
"cssMode": false,
"updateOnWindowResize": true,
"resizeObserver": true,
"nested": false,
"createElements": false,
"enabled": true,
"focusableElements": "input, select, option, textarea, button, video, label",
"width": null,
"height": null,
"preventInteractionOnTransition": false,
"userAgent": null,
"url": null,
"edgeSwipeDetection": false,
"edgeSwipeThreshold": 20,
"autoHeight": false,
"setWrapperSize": false,
"virtualTranslate": false,
"effect": "fade",
"breakpointsBase": "window",
"spaceBetween": 0,
"slidesPerView": 1,
"slidesPerGroup": 1,
"slidesPerGroupSkip": 0,
"slidesPerGroupAuto": false,
"centeredSlides": false,
"centeredSlidesBounds": false,
"slidesOffsetBefore": 0,
"slidesOffsetAfter": 0,
"normalizeSlideIndex": true,
"centerInsufficientSlides": false,
"watchOverflow": true,
"roundLengths": false,
"touchRatio": 1,
"touchAngle": 45,
"simulateTouch": true,
"shortSwipes": true,
"longSwipes": true,
"longSwipesRatio": 0.5,
"longSwipesMs": 300,
"followFinger": true,
"allowTouchMove": true,
"threshold": 5,
"touchMoveStopPropagation": false,
"touchStartPreventDefault": true,
"touchStartForcePreventDefault": false,
"touchReleaseOnEdges": false,
"uniqueNavElements": true,
"resistance": true,
"resistanceRatio": 0.85,
"watchSlidesProgress": false,
"grabCursor": false,
"preventClicks": true,
"preventClicksPropagation": true,
"slideToClickedSlide": false,
"loop": true,
"loopedSlides": null,
"loopPreventsSliding": true,
"rewind": false,
"allowSlidePrev": true,
"allowSlideNext": true,
"swipeHandler": null,
"noSwiping": true,
"noSwipingClass": "swiper-no-swiping",
"noSwipingSelector": null,
"passiveListeners": true,
"maxBackfaceHiddenSlides": 10,
"containerModifierClass": "swiper-",
"slideClass": "swiper-slide",
"slideActiveClass": "swiper-slide-active",
"slideVisibleClass": "swiper-slide-visible",
"slideNextClass": "swiper-slide-next",
"slidePrevClass": "swiper-slide-prev",
"wrapperClass": "swiper-wrapper",
"lazyPreloaderClass": "swiper-lazy-preloader",
"lazyPreloadPrevNext": 0,
"runCallbacksOnInit": true,
"_emitClasses": false,
"observer": true,
"observeParents": false,
"observeSlideChildren": false,
"autoplay": {
"enabled": false,
"delay": 3000,
"waitForTransition": true,
"disableOnInteraction": true,
"stopOnLastSlide": false,
"reverseDirection": false,
"pauseOnMouseEnter": false
},
"navigation": {
"nextEl": ".slider-navigation .slider-next",
"prevEl": ".slider-navigation .slider-prev",
"hideOnClick": false,
"disabledClass": "swiper-button-disabled",
"hiddenClass": "swiper-button-hidden",
"lockClass": "swiper-button-lock",
"navigationDisabledClass": "swiper-navigation-disabled"
},
"fadeEffect": {
"crossFade": true
},
"modules": [
null,
null,
null
]
},
"originalParams": {
"init": true,
"direction": "horizontal",
"oneWayMovement": false,
"touchEventsTarget": "wrapper",
"initialSlide": 0,
"speed": 300,
"cssMode": false,
"updateOnWindowResize": true,
"resizeObserver": true,
"nested": false,
"createElements": false,
"enabled": true,
"focusableElements": "input, select, option, textarea, button, video, label",
"width": null,
"height": null,
"preventInteractionOnTransition": false,
"userAgent": null,
"url": null,
"edgeSwipeDetection": false,
"edgeSwipeThreshold": 20,
"autoHeight": false,
"setWrapperSize": false,
"virtualTranslate": false,
"effect": "fade",
"breakpointsBase": "window",
"spaceBetween": 0,
"slidesPerView": 1,
"slidesPerGroup": 1,
"slidesPerGroupSkip": 0,
"slidesPerGroupAuto": false,
"centeredSlides": false,
"centeredSlidesBounds": false,
"slidesOffsetBefore": 0,
"slidesOffsetAfter": 0,
"normalizeSlideIndex": true,
"centerInsufficientSlides": false,
"watchOverflow": true,
"roundLengths": false,
"touchRatio": 1,
"touchAngle": 45,
"simulateTouch": true,
"shortSwipes": true,
"longSwipes": true,
"longSwipesRatio": 0.5,
"longSwipesMs": 300,
"followFinger": true,
"allowTouchMove": true,
"threshold": 5,
"touchMoveStopPropagation": false,
"touchStartPreventDefault": true,
"touchStartForcePreventDefault": false,
"touchReleaseOnEdges": false,
"uniqueNavElements": true,
"resistance": true,
"resistanceRatio": 0.85,
"watchSlidesProgress": false,
"grabCursor": false,
"preventClicks": true,
"preventClicksPropagation": true,
"slideToClickedSlide": false,
"loop": true,
"loopedSlides": null,
"loopPreventsSliding": true,
"rewind": false,
"allowSlidePrev": true,
"allowSlideNext": true,
"swipeHandler": null,
"noSwiping": true,
"noSwipingClass": "swiper-no-swiping",
"noSwipingSelector": null,
"passiveListeners": true,
"maxBackfaceHiddenSlides": 10,
"containerModifierClass": "swiper-",
"slideClass": "swiper-slide",
"slideActiveClass": "swiper-slide-active",
"slideVisibleClass": "swiper-slide-visible",
"slideNextClass": "swiper-slide-next",
"slidePrevClass": "swiper-slide-prev",
"wrapperClass": "swiper-wrapper",
"lazyPreloaderClass": "swiper-lazy-preloader",
"lazyPreloadPrevNext": 0,
"runCallbacksOnInit": true,
"_emitClasses": false,
"observer": true,
"observeParents": false,
"observeSlideChildren": false,
"autoplay": {
"enabled": false,
"delay": 3000,
"waitForTransition": true,
"disableOnInteraction": true,
"stopOnLastSlide": false,
"reverseDirection": false,
"pauseOnMouseEnter": false
},
"navigation": {
"nextEl": ".slider-navigation .slider-next",
"prevEl": ".slider-navigation .slider-prev",
"hideOnClick": false,
"disabledClass": "swiper-button-disabled",
"hiddenClass": "swiper-button-hidden",
"lockClass": "swiper-button-lock",
"navigationDisabledClass": "swiper-navigation-disabled"
},
"fadeEffect": {
"crossFade": true
},
"modules": [
null,
null,
null
]
},
"passedParams": {
"modules": [
null,
null,
null
],
"loop": true,
"effect": "fade",
"fadeEffect": {
"crossFade": true
},
"centeredSlides": false,
"autoHeight": false,
"observer": true,
"autoplay": {
"enabled": false
},
"navigation": {
"nextEl": ".slider-navigation .slider-next",
"prevEl": ".slider-navigation .slider-prev"
}
},
"enabled": true,
"el": null,
"classNames": [],
"slides": [],
"slidesGrid": [],
"snapGrid": [],
"slidesSizesGrid": [],
"activeIndex": 0,
"realIndex": 0,
"isBeginning": true,
"isEnd": false,
"translate": 0,
"previousTranslate": 0,
"progress": 0,
"velocity": 0,
"animating": false,
"allowSlideNext": true,
"allowSlidePrev": true,
"touchEventsData": {
"focusableElements": "input, select, option, textarea, button, video, label",
"lastClickTime": 0,
"velocities": [],
"evCache": []
},
"allowClick": true,
"allowTouchMove": true,
"touches": {
"startX": 0,
"startY": 0,
"currentX": 0,
"currentY": 0,
"diff": 0
},
"imagesToLoad": [],
"imagesLoaded": 0,
"initialized": false
}

Apparently, a Swiper instance is present but it's not initialized in the first run.
My question is, how can I check for this so the swiperRef.current.destroy(true, true) is not called in the first run?

Thanks in advance

答案1

得分: 1

The Swiper实例对象似乎具有一个 initialized 属性,该属性指示Swiper实例是否已初始化。

您可以使用此属性在销毁之前检查Swiper实例是否已初始化。以下是您可以如何修改您的 useEffect 钩子的方式:

useEffect(() => {
    if (swiperRef.current && swiperRef.current.initialized) {
        // 在更新时销毁Swiper实例。
        swiperRef.current.destroy(true, true);
    }
    // 初始化Swiper实例。
    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]);

这样,只有在Swiper实例存在且已初始化时才会调用 swiperRef.current.destroy(true, true)

英文:

The Swiper instance object seems to have an initialized property which indicates if the Swiper instance is initialized or not.

当属性更新时销毁并重新初始化Swiper实例。

You can use this property to check if the Swiper instance is initialized before destroying it. Here's how you can modify your useEffect hook -->

useEffect(() => {
if (swiperRef.current && swiperRef.current.initialized) {
// 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]);

This way, swiperRef.current.destroy(true, true) will only be called if the Swiper instance exists and it's initialized.

huangapple
  • 本文由 发表于 2023年6月13日 17:53:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/76463679.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定