TypeError reading '_emitClasses' when instance is destroyed before first update (Vue and React)
Check that this is really a bug
- I confirm
Reproduction link
https://e7webbe6.stackblitz.io (Vue), https://uqcs9xky.stackblitz.io (React)
Bug description
onUpdated in swiper-vue.mjs calls emitSlidesClasses() without checking destroyed.
The updateSwiper branch a few lines below does check it.
onUpdated(() => {
if (!initializedRef.value && swiperRef.value) {
swiperRef.value.emitSlidesClasses(); // no destroyed check
initializedRef.value = true;
}
...
if ((changedParams.length || breakpointChanged.value) && swiperRef.value && !swiperRef.value.destroyed) {destroy(true) runs deleteProps(swiper), which removes swiper.params.
emitSlidesClasses() then reads swiper.params._emitClasses and throws.
Two things have to line up. The instance must be destroyed before the component's first
update, while initializedRef is still false. The Swiper must also have no slides,
otherwise SwiperSlide's render throws first on swiperRef.value.params.loop.
The reproduction calls destroy(true, false), which is what the wrapper itself does in
onBeforeUnmount. We hit it on a fast route change, where the component renders once and
unmounts in the same Vue flush, so the queued onUpdated runs after the instance was
destroyed. The throw happens inside Vue's post-flush queue, so the rest of that batch never
runs and other components stop updating.
Fix:
- if (!initializedRef.value && swiperRef.value) {
+ if (!initializedRef.value && swiperRef.value && !swiperRef.value.destroyed) {swiper-react.mjs has the same unguarded call and throws the same way:
useEffect(() => {
if (!initializedRef.current && swiperRef.current) {
swiperRef.current.emitSlidesClasses(); // no destroyed check
initializedRef.current = true;
}
});React reproduction: https://uqcs9xky.stackblitz.io (swiper 14.2.0, react 18.3.1)
There it takes even less to hit. That effect runs after layout effects, so destroying the instance from a layout effect is enough and no update is needed, it throws on mount. The sandbox has an error boundary so the message stays on screen. Without one the error reaches the root and React unmounts the whole tree, leaving a blank page.
Expected Behavior
onUpdated skips a destroyed instance, the same way the updateSwiper branch below it does.
No error is thrown.
Actual Behavior
TypeError: Cannot read properties of undefined (reading '_emitClasses')
at Swiper.emitSlidesClasses (swiper-core.mjs)
at swiper-vue.mjs (onUpdated)React:
TypeError: Cannot read properties of undefined (reading '_emitClasses')
at _Swiper.emitSlidesClasses (swiper-core.mjs)
The above error occurred in the <Swiper> componentSwiper version
12.0.3 (also present in 14.2.0)
Platform/Target and Browser Versions
macOS 26.6.2, Chrome 152.0.7977.66; Vue 3.5.40 and React 18.3.1, Vite 6
Validations
- Follow our Code of Conduct
- Read the docs.
- Check that there isn't already an issue that request the same feature to avoid creating a duplicate.
- Make sure this is a Swiper issue and not a framework-specific issue
Would you like to open a PR for this bug?
- I'm willing to open a PR
Source: nolimits4web/swiper