This is a (multiple allowed):
A callback in my react component is set to swiper/react component, and I want to update that function
callback function would be updated
please refer to the provided codesandbox link, reproducing steps:
List in onSlideChange Cb wouldn't be updated because list in the callback stays the sameI am not sure if this is related to how event listeners are updated to the swiper instance from react component. I quickly checked the source code but I can't find any clue. I think it might be much easier to look for help here so if someone can give me some hint that would be really appreciated!
I workaround by adding event listeners to swiper instance in useEffect hook, ie.
const Component = () => {
const [swiperInstance, setSwiperInstance] = useState(null);
const onSlideChange = useCallback(() => {
setListInCb(list);
}, [list]);
useEffect(() => {
if (swiperInstance) {
swiperInstance.on("slideChange", onSlideChange);
}
}, [swiperInstance, onSlideChange]);
return (
<Swiper navigation>
{items}
</Swiper>
);
}
File: App_fixed.jsx
const onRandomClick = useCallback(() => {
setList([
{
id: Math.floor(10 * Math.random())
},
{
id: Math.floor(10 * Math.random())
},
{
id: Math.floor(10 * Math.random())
}
]);
}, []);
I added new item, but swper items are not update after clicked.
May need to call swiper.updateSlides()
useRef as another workaround to get latest state value in the component when onSlideChange not get updated.
import React, { useState, useCallback, useRef } from "react";
import SwiperCore, { Navigation } from "swiper";
import { Swiper, SwiperSlide } from "swiper/react";
import "./styles.css";
SwiperCore.use([Navigation]);
export default function App() {
const listRef = useRef(null);
const [list, setList] = useState([
{
id: "1"
},
{
id: "2"
}
]);
const setListAndRef = (l) => {
setList(l);
listRef.current = l;
};
const [listInCb, setListInCb] = useState(list);
const onSlideChange = useCallback(() => {
// list stays the same as the intial value
console.log(JSON.stringify(listRef.current));
setListInCb(listRef.current);
}, []);
const onRandomClick = useCallback(() => {
setListAndRef([
{
id: Math.floor(1000 * Math.random())
},
{
id: Math.floor(1000 * Math.random())
}
]);
}, []);
const items = list.map((li) => (
<SwiperSlide key={li.id}>{li.id}</SwiperSlide>
));
return (
<div className="App">
<Swiper navigation onSlideChange={onSlideChange}>
{items}
</Swiper>
<button type="button" onClick={onRandomClick}>
Random list
</button>
<p>List in onSlideChange Cb</p>
{JSON.stringify(listInCb)}
</div>
);
}
based on your example
https://codesandbox.io/s/swiper-event-listener-forked-pe3ex?file=/src/App.js:0-1295
also same with onClick callback
can it be fixed?
From what I can gather, https://github.com/nolimits4web/swiper/blob/f8ca5c094b7fa5d361b80510340256ecbfca75f9/src/react/get-changed-params.js should properly notice that the event handler changed.
Then https://github.com/nolimits4web/swiper/blob/f8ca5c094b7fa5d361b80510340256ecbfca75f9/src/react/update-swiper.js doesn't do anything with that info.
It would need to .off and .on the changed event handlers.
Most helpful comment
useRefas another workaround to get latest state value in the component whenonSlideChangenot get updated.based on your example
https://codesandbox.io/s/swiper-event-listener-forked-pe3ex?file=/src/App.js:0-1295