<div id="app"></div>
.app-body {
  display: flex;
  justify-content: center;
}
.slider-container {
  display: flex;
  align-items: center;
  margin-top: 50px;
}
.slider-container img {
  width: 600px;
  height: 400px;
}
.previous-button {
  font-size: 30px;
  background-color: rgb(0, 0, 0, 0.25);
  height: 45px;
  transform: translate(60px, 0);
}
.next-button {
  font-size: 30px;
  background-color: rgb(0, 0, 0, 0.25);
  height: 45px;
  transform: translate(-60px, 0);
}
/*
 * https://frontendeval.com/questions/image-carousel
 *
 * Build an auto-playing image carousel
 */

import { useState, useEffect } from "https://cdn.skypack.dev/react@17.0.1";

const alt =
  "Ever since my niece saw Toy Story, she shouts “I’m leaving!” and then peeks at her room like this";

const Slider = ({ alt }) => {
  const [srcArray, setSrcArray] = React.useState([]);
  const [slide, setSlide] = React.useState(0);
  const URL = "https://www.reddit.com/r/aww/top/.json?t=all";

  const getImages = async () => {
    try {
      const response = await fetch(URL);
      if (response.ok) {
        const data = await response.json();
        const dataMap = (d) => d.data.url_overridden_by_dest;
        const images = data.data?.children
          .map(dataMap)
          .filter((url) => url.slice(-3) === "jpg");
        setSrcArray(images);
      }
    } catch (e) {
      console.log("er", e);
    }
  };

  React.useEffect(() => {
    getImages();
  }, []);

  React.useEffect(() => {
    const timeoutID = setTimeout(() => {
      setSlide((s) => (s === srcArray.length - 1 ? 0 : s + 1));
    }, 3000);
    return () => clearTimeout(timeoutID);
  }, [slide]);

  return (
    <>
      {srcArray.length > 0 && (
        <div className="slider-container">
          <button
            className="previous-button"
            onClick={() => {
              setSlide((s) => (s === srcArray.length - 1 ? 0 : s - 1));
            }}
          >
            ◀️
          </button>
          <img src={srcArray[slide]} alt={alt} />
          <button
            className="next-button"
            onClick={() =>
              setSlide((s) => (s === srcArray.length - 1 ? 0 : s + 1))
            }
          >
            ▶️
          </button>
        </div>
      )}
    </>
  );
};

const App = () => {
  return (
    <div className="app-body">
      <Slider alt={alt} />
    </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