Skip to content

useComputed() recomputes on unrelated renders β€” even when tracked signal values haven't changedΒ #772

@manic2500

Description

@manic2500

πŸ› Bug Report

When using useComputed() in a React component with @preact/signals-react, the computed function unexpectedly re-runs on every component re-render β€” even when none of the signals used inside it have changed.

This breaks expectations and hurts performance when used with expensive calculations.


βœ… Expected Behavior

useComputed(() => expensiveFn(signal.value)) should only re-run when the dependent signal (signal.value) changes β€” not when unrelated state/signal updates cause a component re-render.


❌ Actual Behavior

The computed function runs again on every render, even if the signal used (count.value below) hasn't changed.


Behavior Observed:

console.log("Calculating...") fires every time the input value changes (even though count.value is untouched).

πŸ” Reproduction Steps

import React from "react";
import { useComputed, useSignal } from "@preact/signals-react";

const expensiveCalculation = (num) => {
  console.log("Calculating...");
  for (let i = 0; i < 10000000; i++) {
    num += 1;
  }
  return num;
};

export default function Demo() {
  const count = useSignal(0);
  const newTask = useSignal("");

  const double = useComputed(() => expensiveCalculation(count.value));

  return (
    <div>
      <h2>Count: {count.value}</h2>
      <h2>Doubled: {double.value}</h2> {/* <-- accessing .value seems to trigger recompute */}
      <button onClick={() => count.value++}>Increment</button>

      <input
        type="text"
        value={newTask.value}
        onChange={(e) => newTask.value = e.target.value}
      />
    </div>
  );
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions