Infinite re-render loop when dragging a controlled index slider while using on.view #392
-
When using the Inline plugin with a controlled index prop and an external slider to navigate slides, dragging the slider thumb vigorously causes this error:Maximum update depth exceeded. This can happen when a component calls setState Reproduction: import "yet-another-react-lightbox/styles.css";
import { useEffect, useState } from "react";
import { Range } from "react-range";
import axios from "axios";
import Lightbox from "yet-another-react-lightbox";
import Inline from "yet-another-react-lightbox/plugins/inline";
export default function Reproduce() {
const [slides, setSlides] = useState([]);
const [loading, setLoading] = useState(false);
const [index, setIndex] = useState(0);
useEffect(() => {
async function fetchImages() {
setLoading(true);
try {
const response = await axios.get(
"https://picsum.photos/v2/list?page=1&limit=50",
);
const slides = response.data.map((img) => {
return { src: img.download_url };
});
setSlides(slides);
} catch (e) {
console.log(e);
} finally {
setLoading(false);
}
}
fetchImages();
}, []);
const slidesLength = slides.length - 1;
if (loading) {
return <div>Loading...</div>;
}
return (
<div
style={{
position: "fixed",
inset: 0,
display: "grid",
gridTemplateRows: "7fr 1fr",
}}
>
<div>
<Lightbox
slides={slides}
index={index}
plugins={[Inline]}
on={{
view: ({ index: currentIndex }) => {
setIndex(currentIndex);
},
}}
/>
</div>
<div style={{ marginTop: "1rem", width: "70%", marginInline: "auto" }}>
{slides.length && (
<Range
label="Page Slider"
step={1}
min={0}
max={slidesLength}
values={[index]}
onChange={(e) => setIndex(e[0])}
renderTrack={({ props, children }) => (
<div
{...props}
style={{
...props.style,
height: "6px",
width: "100%",
backgroundColor: "#000",
}}
>
{children}
</div>
)}
renderThumb={({ props }) => (
<div
{...props}
key={props.key}
style={{
...props.style,
height: "15px",
width: "15px",
backgroundColor: "pink",
borderRadius: "20px",
}}
/>
)}
renderMark={({ props }) => {
return (
<div
{...props}
key={props.key}
style={{
...props.style,
height: "20px",
width: "5px",
backgroundColor: "red",
}}
></div>
);
}}
/>
)}
</div>
</div>
);
}Steps to reproduce:
Expected: Slider jumps to the selected slide smoothly Thanks! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
hello, I got a workaround: Wrap the const deferredIndex = useDeferredValue(index);
<Lightbox
index={deferredIndex}
on={{
view: ({ index: currentIndex }) => setIndex(currentIndex),
}}
/>This works because |
Beta Was this translation helpful? Give feedback.
@realrnvr
Thanks for reporting this! You've uncovered a genuine bug — when the
indexprop changes rapidly (e.g., from a slider during drag), the lightbox's internal state sync can fall one render behind, causingon.viewto fire with a staleindexvalue. This creates a feedback loop where the parent state and lightbox state chase each other indefinitely.I'll create a ticket to fix the root cause on the library side (see #395 for updates).
In the meantime, wrapping the index with
useDeferredValuebefore passing it to the lightbox is a solid workaround — and arguably a good practice regardless of this bug, since it lets React deprioritize the lightbox update during rapid input and keeps the…