vanjs-org/van

State change in setInterval

Closed this issue · 6 comments

I've been building an app with VanJS. The experience is fantastic (kinda reminds me of Flutter).

However, I have run into a weird issue when updating a state var in a set timeout. This is the component code:

export default function App() {
  const timeout = van.state(10);

  van.derive(() => {
    const interval = setInterval(() => {
      if (timeout.val === 0) {
        clearInterval(interval);
      }

      --timeout.val;
     console.log(timeout.val)
    }, 1000);
  });

  return div("Title", p(`Countdown: ${timeout.val}s`));
}

The issue is the on every tick, the console logs multiple times. I may be wrong, but I suspect the setInterval is being called multiple times because a state is being mutated in it.

The requirement here is the start a timer when the component is loaded...

You don't need to wrap the setInterval with van.derive. Just simply having the code below will be enough:

const interval = setInterval(() => {
  if (timeout.val === 0) {
    clearInterval(interval);
  }

  --timeout.val;
  console.log(timeout.val)
}, 1000);

I tried this, but the timer keeps getting duplicated and started resulting in multiple countdowns in the console.
image

This is the code I'm working with.

image

The thing is the counter in the text, never changes from the initial 5 also, which is weird.

Ah, you should wrap the text inside a binding function. Specifically, change:

p(`Countdown: ${timeout.val}s`)

to

p(() => `Countdown: ${timeout.val}s`)

Wow. That actually fixed both issues. Could u please explain why this is?

For a state-derived child element, you need to specify a binding function to bind the element with the underlying states. You can refer to this section for more details: https://vanjs.org/tutorial#state-derived-child.