Back

A CallBack, Modulo, and setInterval Walk into a Bar...

30 Mar 2025

main image for A CallBack, Modulo, and setInterval Walk into a Bar...

I was working on a project that required cycling through an array of words and displaying them one at a time. Sounds simple. Show a word, wait a few seconds, show the next — and loop it forever.

My instinct? A loop. That’s always been my go-to when iterating over arrays — like a trusty six-shooter at my side.

But this time, nothing was firing properly. I’ve never been super confident with JavaScript timing functions like setTimeout or setInterval, but I knew this problem lived there. As I dug deeper, I realized the tools I thought I needed weren’t the ones I actually needed.

Enter: the callback function, the modulo operator, and the often misunderstood setInterval.

Those three didn’t just wrangle my problem — they changed the whole corral.

My First Attempt: forEach + setTimeout

My first instinct was to use forEach. I thought I could loop through the words and delay each one using setTimeout. In theory, this should’ve worked:

const words = ['Innovate', 'Elevate', 'Create'];

words.forEach((word) => {
  setTimeout(() => {
    console.log(word);
  }, 2000);
});

WRONG

This approach worked once — and then stopped. No loop. No reactivity. No way to update the UI properly in React.

setInterval: What I Actually Needed

After realizing that forEach and setTimeout weren’t going to cut it, I turned to setInterval. I knew it ran a block of code every X milliseconds, but I’d never used it confidently inside a React component.

setInterval(() => {
  console.log('This runs every 2 seconds');
}, 2000);

Simple enough — but in React, we don’t just log things. We update state. So I wrapped the interval inside useEffect and tracked the current index with useState.

const [index, setIndex] = useState(0);

useEffect(() => {
  const interval = setInterval(() => {
    setIndex((prevIndex) => prevIndex + 1);
  }, 2000);

  return () => clearInterval(interval);
}, []);

Every two seconds, state updated, React re-rendered, and the UI changed. Sweet! But there was still a problem… what happens when the index reaches the end of the array?

Western-style showdown illustration

Modulo — My New Favorite Loop

The index just kept climbing forever and eventually crashed the app. Arrays don’t appreciate being asked for words[1000]. What I needed was a way to loop back to the beginning.

That’s when the modulo operator (%) strolled in, tipped its hat, and said: I’ll take it from here.

const nextIndex = (prevIndex + 1) % words.length;

This single line increments the index and resets it to 0 when it reaches the end of the array. Simple math. Perfect loop.

The Final Working Solution

const words = ['Innovate', 'Elevate', 'Create', 'Accelerate'];
const [index, setIndex] = useState(0);

useEffect(() => {
  const interval = setInterval(() => {
    setIndex((prevIndex) => (prevIndex + 1) % words.length);
  }, 2000);

  return () => clearInterval(interval);
}, []);

{words[index]}

Final Thoughts

This was one of those moments where I had to unlearn what I thought I knew. I wanted to reach for a loop because loops feel natural with arrays — but React and time-based updates play by different rules.

The real solution came from combining a state callback, the modulo operator to create a loop, and setInterval to drive timing.

Moral of the story? If an array walks into a bar… don’t automatically pull a loop on ’em.