Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[2.0] Effects re-run (and run cleanup) when the compute returns an equal value; there's no `equals` option

Open
#4,184 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@ryansolid is already working on this.

Since Oct 21, 2026.

  • #4197 by @ryansolid — open

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
54/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
typescript

Research direction

Start with packages/signals/src/signals.ts and inspect EffectOptions, createEffect, and createRenderEffect; the report says an equals option is currently ignored and gives a signals-only reproduction. Run that reproduction or add a focused test for repeated equal compute results, including cleanup counts. Done means the chosen behavior is implemented and verified, or the reactivity documentation clearly explains the current behavior and memo workaround.

Written by the indexing model from the issue text.

Description

Describe the bug

createEffect(compute, effectFn) and createRenderEffect re-run the effect function, and the previous cleanup, every time a tracked read changes, even when compute returns the same value as before. EffectOptions (packages/signals/src/signals.ts) has no equals, and passing one is silently ignored.

Your Example Website or App

Minimal repro inline below (signals-only). Real-world occurrence: https://github.com/openclaw/openclaw/blob/1989e3dc436/.agents/skills/solid/references/lessons.md#L8

Steps to Reproduce the Bug or Issue
import { createSignal, createRoot, createEffect, createMemo, flush } from "@solidjs/signals";

let applies = 0, cleanups = 0;
const [n, setN] = createSignal(1);
createRoot(() => createEffect(() => n() > 0, () => { applies++; return () => { cleanups++; }; }));
flush(); setN(2); flush(); setN(3); flush();
// compute returned true three times
Setup computes applies cleanups
Plain 3 3 2
createMemo(() => n() > 0) in front 1 0
{ equals: (a, b) => a === b } passed as options 3 (ignored)

createRenderEffect gives the same numbers.

Expected behavior

Either:

  • the effect skips its apply and cleanup when the compute result is equal (using the same default equals as memos, or an equals option on effects); or
  • the reactivity docs and cheatsheet state the current behavior clearly and recommend a memo in front. An unknown equals option could also warn in dev instead of being silently ignored.
Screenshots or Videos

No response

Platform
  • OS: macOS (Darwin 25.5)
  • Browser: n/a (reproduced in Node v24.18.0 with vitest, importing source)
  • Version: solid next @ b0ad1df50 (2026-10-20, after 2.0.0-rc.16)
Additional context
  • React developers assume the opposite: useEffect skips when its dependencies are unchanged.
  • Cleanups churn: because cleanups re-run, subscriptions and timers are torn down and restarted on unrelated changes.
  • Seen in production: OpenClaw hit this in production. A props refresh re-ran an effect with an unchanged status, which cancelled a timer and never restarted it (https://github.com/openclaw/openclaw/blob/1989e3dc436/.agents/skills/solid/references/lessons.md#L8).
  • Documented as a pitfall: the From React additions (solidjs/solid-docs#1664) describe this.
Dominant language
TypeScript
Stars
36.1k
Forks
1.1k
Avg merge
11h 42m
Merged PRs (30d)
350

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from solidjs/solid

All issues in solidjs/solid

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.