Why does Solid.js createEffect not re-run when a signal is in a setTimeout callback?

Viewed 492

In Solid, why does this effect not re-run when count is updated? After some tinkering, I've found that it has to with count being in the setTimeout callback function, but what's the intuitive way to understand what things inside an effect are tracked and what things aren't?

function Counter() {
  const [count, setCount] = createSignal(0);

  createEffect(() => {
    setTimeout(() => {
      setCount(count() + 1);
    }, 1000);
  })

  return (
    <>
      {count()}
    </>
  );
}
1 Answers

You can think about it this way (this is pretty much how the source code works):

let Listener

function Counter() {
  const [count, setCount] = createSignal(0);

  createEffect(() => {
    Listener = thisEffect
    setTimeout(() => {
      setCount(count() + 1);
    }, 1000);
    Listener = null
  })

  return (
    <>
      {count()}
    </>
  );
}

As you can see the effect will set itself as the listener (tracking context) when the function starts and then will reset the listener (to the previous listener if it exists, in this case it doesn't).

So the effect will be the tracking context only during the execution of the callback you provided to createEffect as the argument. setTimeout delays the execution of whatever you put in it, so once the callback you put in setTimeout executes, the effect callback will have already finished executing, which means that it has already reset the listener, so the effect is not listening to signals anymore.

Related