I'm trying to animate my react-slick
slides when they enter into the viewport by detecting when the slide elements intersect with my root element using the IntersectionObserver
API.
This is working as expected.
What isn't working is, when react-slick
loops back from :last-slide
to :first-slide
, that first react component seems to lose its state momentarily before "catching up" - even though it has already been rendered.
I've demonstrated this in two places, once using the native IntersectionObserver API and once using a React Wrapper around the native API - react-intersection-observer
.
The full code of what I have so far is below and in the sandboxes here:
Native: https://codesandbox.io/s/react-slick-and-native-intersection-observer-cqtmv
React Wrapper: https://codesandbox.io/s/react-slick-and-react-intersection-observer-qvbum
const ReactSlickDemo = () => {
const useStyles = makeStyles(theme => ({
root: {
display: "flex",
justifyContent: "center",
flexWrap: "wrap",
"& > *": {
margin: theme.spacing(0.5)
}
},
container: {
padding: "40px",
background: "#419be0",
"& .slick-slide img": {
margin: "auto"
}
},
initFadeIn: {
"& *": {
opacity: 0,
"& img": {
opacity: 1
},
"& [class*=SWRecordHeader-images-]": {
opacity: 1
}
},
"& [class*=SWRecordHeader-inner-]": {
opacity: 1
}
},
runFadeIn: {
"& *": {
opacity: 1
}
},
initSlideUp: {
"& *": {
webkitTransform: "translateY(30px)",
transform: "translateY(30px)",
"& img": {
webkitTransform: "translateY(-30px)",
transform: "translateY(-30px)"
},
"& [class*=SWRecordHeader-images-]": {
webkitTransform: "unset",
transform: "unset"
}
}
},
runSlideUp: {
"& *": {
webkitTransform: "translateY(0px)",
transform: "translateY(0px)",
"& img": {
webkitTransform: "translateY(0px)",
transform: "translateY(0px)"
}
}
},
initTransition: {
"& *": {
webkitTransition: "all 0.6s ease-in-out",
transition: "all 0.6s ease-in-out"
}
}
}));
const classes = useStyles();
const Component = () => {
const [toggle, setToggle] = useState(false);
const el = useRef(null);
useEffect(() => {
console.log("effect!");
const node = el.current;
const options = {
threshold: 0.5
};
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting && !toggle) setToggle(true);
console.log(toggle);
});
}, options);
observer.observe(node);
return () => observer.unobserve(node);
}, [toggle, el]);
return (
<div
ref={el}
className={clsx(
classes.initTransition,
classes.initFadeIn,
classes.initSlideUp,
{
[classes.runFadeIn]: toggle,
[classes.runSlideUp]: toggle
}
)}
>
<img src="http://placekitten.com/g/400/200" alt="test" />
</div>
);
};
return (
<div className={classes.container}>
<Slider dots>
{[1, 2, 3, 4].map(item => (
<Component />
))}
</Slider>
</div>
);
};