<div id="app"></div>
*,*::before,*::after {
  box-sizing:border-box;
  margin:0;
}

.carousel-container{
  height:100vh;
  width:100vw;
  display:flex;
  position:relative;
}
.carousel-img {
  position:absolute;
  inset:0;
  height:100%;
  width:100%;
  object-fit:cover;
  object-position:center;
  opacity:0;
  transition:200ms opacity ease-in;
  transition-delay:200ms;
}
.carousel-img.active {
  opacity:1;
  transition-delay:0ms;
}
.carousel-btn{
  position:absolute;
  cursor:pointer;
  top:50%;
  font-size:4rem;
  z-index:2;
  background:none;
  border:none;
  transform:translateY(-50%);
  color:rgba(255,255,255,0.5);
  background-color:rgba(0,0,0,0.1);
  border-radius:0.25rem;
  padding:0.5rem;
}
.carousel-btn:hover,
.carousel-btn:focus {
  color:white;
  background-color:rgba(0,0,0,0.2);
}
.carousel-btn:focus {
  outline:2px solid black;
}
.carousel-btn.prev{
  left:1rem;
}
.carousel-btn.next{
  right:1rem;
}
const {useEffect,useState,useRef} = React
const URL = `https://www.reddit.com/r/aww/top/.json?t=all`

const App = () => {
  const [images, setImages] = useState([])
  const [errorImg, setErrorImg] = useState("")
  const [slide,setSlide] = useState(0)
  
  const handleNext = ()=> {
    setSlide(prev => prev === images.length-1 ? 0: prev+1)
  }
   const handlePrev = ()=> {
    setSlide(prev => prev === 0 ? images.length-1: prev-1)
  }
  
  if(errorImg.length > 0){
    <p>{`Error Fetching images ${errorImg}`}</p>
  }
  useEffect(()=>{
    console.log("ONCE FETCH")
    fetch(URL).then(res => res.json()).then(final => {
      const data = final.data.children.map(o => o.data.url_overridden_by_dest).filter(url => url.slice(-4) === ".jpg")
      setImages(data)
    }).catch(err  => setErrorImg(err))
  },[])
  
  const ref = useRef()
  useEffect(()=>{
    console.log("Always")
    ref.current = handleNext
  })
  useEffect(()=>{
    console.log("SET INTERVAL ONE")
    
    if(ref.current != null){
       const id = setInterval(()=>{
         ref.current()
       },3000)
    }
    return ()=> clearInterval(id)
  },[])
  
  const imageData = images.length === 0 ? <p>Loading...</p> : images.map((img,idx) => <img src={img} alt="response img" key={img} className={`carousel-img ${idx === slide ? "active":""}`}/>)
  return <div className="carousel-container">
    <button onClick={handleNext} className="carousel-btn next">&#8667;</button>
    <button  onClick={handlePrev} className="carousel-btn prev">&#8666;</button>
    {imageData}
  </div>
}

ReactDOM.render(<App />, document.getElementById('app'));
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js