DEV Community

Anxiny
Anxiny

Posted on

16 3

Create a Slideshow With React

Let's create a simple slideshow component today. It's easy and only take few steps to achieve.
Here is a demo and source code.

In order to create a slideshow, we need to have two components:

  • The container that holds contents.
  • The individual slide.

Container

For a slideshow, we need a container that can:

  • contain all slides.
  • hide slides that outside viewport of the container.
  • sent a signal that tells slides to move in.
  • sent a signal that tells slides to move out.
  • track which slide should be shown.

First, let's create a basic container with style:

export function Slideshow({ children, className, style }) {
  return (
      <div
        style={{
          height: "600px",
          width: "600px",
          position: "relative",
          overflow: "hidden"
        }}
      >
        {children}
      </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Second, let's add a context that will track activated slide and a timer:

const SlideshowContext = createContext();

export function Slideshow({ children, className, style }) {
  const [context, setContext] = useState({
    items: [],
    edge: false
  });
  const timer = useRef(null);

  useEffect(() => {
    if (timer.current) clearTimeout(timer.current);
    timer.current = setTimeout(() => {
      // Move deactivated slide out when edge is false
      // Move activated slide in when edge is true
      if (context.items.length > 1 && context.edge) {
        const head = context.items.shift();
        context.items.push(head);
      }
      context.edge = !context.edge;
      setContext({ ...context });
    }, 2500);

    return () => clearTimeout(timer.current);
  });

  console.log(context.items);

  return (
    <SlideshowContext.Provider value={[context, setContext]}>
      <div
        style={{
          height: "600px",
          width: "600px",
          position: "relative",
          overflow: "hidden"
        }}
      >
        {children}
      </div>
    </SlideshowContext.Provider>
  );
}
Enter fullscreen mode Exit fullscreen mode

And that's all for the container.

Slide

The slide will have at least three stages:

  • on stage - slide is in viewport and has highest z-index.
  • off stage - slide is in viewport and has lowest z-index
  • ready for stage - slide is moved out from viewport, and it's waiting at ready position.

The reason we don't move out the slide at "off stage", is because, for this slideshow, we want to move "off" slide after the "on" slide completely cover the "off" one.

Slide will update it's stage when received signal from the container, so it will like:

  1. slide at ready position.
  2. when signal come and the slide is activated, moved to viewport.
  3. when signal come and the current slide is not the activated one, lower the z-index.
  4. when next signal come, move to ready position.

So, we can have something like this:

export function SlideshowItem({ children }) {
  const name = useRef(`${performance.now()}_${Math.random()}`);
// Generate a name for this slide.
  const [context] = useContext(SlideshowContext);
  const [stage, setStage] = useState("ready");

  useEffect(() => {
    // register self with the name.
    context.items.push(name.current);
    return () => {
      // Remove the name when slide is removed.
      const index = context.items.indexOf(name.current);
      context.items.splice(index, 1);
    };
  }, []);

  useEffect(() => {
    const activeName = context.items[0];
    if (activeName === name.current) {
      setStage("on");
    }
    if (activeName !== name.current && stage === "on") {
      setStage("off");
    }
    if (activeName !== name.current && stage === "off") {
      setStage("ready");
    }
  }, [context]);

  let left = 0;
  let zIndex = 0;
  switch (stage) {
    case "ready":
      left = "100%";
      break;
    case "on":
      left = "0";
      zIndex = 1;
      break;
    case "off":
      zIndex = 0;
      break;
    default:
  }

  return (
    <div
      style={{
        transition: "0.5s",
        position: "absolute",
        top: 0,
        left: left,
        zIndex: zIndex
      }}
    >
      {children}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

And now, we have a simple Slideshow.
Thanks all!

Tiugo image

Modular, Fast, and Built for Developers

CKEditor 5 gives you full control over your editing experience. A modular architecture means you get high performance, fewer re-renders and a setup that scales with your needs.

Start now

Top comments (0)

Jetbrains image

Build Secure, Ship Fast

Discover best practices to secure CI/CD without slowing down your pipeline.

Read more

👋 Kindness is contagious

Dive into this insightful write-up, celebrated within the collaborative DEV Community. Developers at any stage are invited to contribute and elevate our shared skills.

A simple "thank you" can boost someone’s spirits—leave your kudos in the comments!

On DEV, exchanging ideas fuels progress and deepens our connections. If this post helped you, a brief note of thanks goes a long way.

Okay