Skip to content

upgrade: timer package upgrade for Solid 2.0#843

Draft
davedbase wants to merge 3 commits intosolidjs-community:mainfrom
davedbase:update/v2/timer
Draft

upgrade: timer package upgrade for Solid 2.0#843
davedbase wants to merge 3 commits intosolidjs-community:mainfrom
davedbase:update/v2/timer

Conversation

@davedbase
Copy link
Copy Markdown
Member

@davedbase davedbase commented Apr 18, 2026

Reimplements the timer package for solid-js@2.0.0.

  • makeTimer no longer auto-registers with onCleanup — it returns a cleanup function and lets the caller decide. createTimer and createTimeoutLoop call onCleanup(makeTimer(...)) at their own call sites. This aligns with the make* / create* naming convention used across solid-primitives.
  • isServer is now imported from @solidjs/web (moved out of solid-js/web in 2.0).
  • createEffect updated to the split compute/apply model: createEffect(compute, apply). The apply phase returns a cleanup function instead of using onCleanup (which doesn't work in the apply phase).
  • batch removed — signal writes are auto-batched via microtask in 2.0. Tests use flush() where synchronous commitment is needed.
  • The reconciliation logic in createTimer (fractional delay carry-over) is rewritten to manage the full timer lifecycle directly in the apply cleanup closure, replacing the 1.x signal self-trigger trick.

Bug fix: createPolled — issue #808

The original implementation used createMemo(() => createSignal(fn(value), options)) and called memo()[1](fn) from the timer. In production builds memo()[1] was undefined, crashing on every timer tick.

The fix captures the signal setter in a closure variable that is updated each time the memo re-runs:

let set!: Setter<T>;
const memo = createMemo(() => {
  const [get, _set] = createSignal<T>(fn(value) as Exclude<T, Function>, options);
  set = _set;
  return get;
});
untrack(memo); // force initial evaluation so `set` is defined before the timer fires
createTimer(() => set(prev => fn(prev)), timeout, setInterval);
return () => memo()();

I'm not fully confident in this createPolled fix and would welcome a second look. The main concern is whether capturing set in a closure and updating it on each memo re-run (dep change) is the right pattern in Solid 2.0, or whether there's a cleaner approach using the new writable derived signal (createSignal(computeFn, initialValue, options)) that avoids the TypeScript overload discrimination issues we ran into.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Apr 18, 2026

⚠️ No Changeset found

Latest commit: 71c6e9d

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@davedbase davedbase marked this pull request as draft April 20, 2026 02:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant