useEffect dependency array like it just insulted your family? Yep. Same. And exact kind of pain is why signals vs hooks is suddenly a real conversation for React devs. Not because Hooks are “bad.” They’re not. It’s because signals change the shape of reactivity, and once you see it, you can’t unsee it. React Hooks like useState and useEffect are still the default mental model in React. But signals, popularized by Solid and picked up in different forms by Preact and Angular, nudge you toward fine-grained updates, where the framework updates only the bits that actually depend on the value changed. If you want a visual anchor, a simple diagram showing component re-render vs reactive graph updates clears up a lot. Alt text: “Signals vs Hooks reactivity model: React re-renders component tree. Signals update only subscribed computations and DOM nodes.”Key takeaways, without the fluff
- Hooks re-run components when state changes. Signals aim for fine-grained updates, often skipping full component re-execution. - Signals usually track dependencies by reading values. Hooks lean on explicit dependency arrays like
useEffect,useMemo,useCallback. - In React today, signals usually show up through libraries like@preact/signals-react, and you’ll often want a Babel transform if you want the “nice” ergonomics. - React is also trying to make manual optimization less of a full-time job with React Compiler, which auto-memoizes and can reduce cascading re-renders. - Signals can be great for reactive-heavy UIs, but you still have to think about SSR, integration limits, and team conventions. No free lunch. ---
Signals vs Hooks: what’s the real difference?
Hooks: re-render + reconcile, on purpose
React’s model is pretty clean. Update state, React re-runs your component, then it reconciles the virtual DOM with the real DOM. That’s literally what “trigger a re-render” means in the Hook world, and React is very upfront about it in the docs for useState. [React useState]
Then there’s useEffect. React tries to keep rendering kinda pure, so effects run after commit, and you handle dependency tracking yourself. If you’ve ever shipped a stale-closure bug, you. know how “fun” that can be. [React useEffect]
Signals: fine-grained reactivity + automatic dependency tracking
Signals are reactive primitives. A signal wraps a value. When something reads it, it subscribes.Yet the value changes, only the subscribers update. Solid explains it in plain terms: signals collect dependencies inside tracking scopes and notify subscribers when the value changes. [Solid signals docs]
And LogRocket frames the big contrast as fine-grained reactivity vs React’s “re-render and diff.”
[LogRocket]
Signals vs Hooks in practice: same UI, different feel
Let’s do the classic counter. Because of course. ### React Hooks version
import { useState } from "react". Export function Counter() {
const [count, setCount] = useState;
return => setCount}>
Count: {count}
</button>
). }Clean. Familiar. But yep, the component function runs again every time you call setCount. ### Signals in React, using @preact/signals-react
Install:
npm install @preact/signals-reactThen:
import { signal } from "@preact/signals-react";
const count = signal. Export function Counter() {
return =>}>
Count: {count.value}
</button>
). }Here’s the fun part. The React adapter supports optimizations where passing the signal directly into JSX can update a text node without re-rendering the surrounding component, which is spelled out in the docs. [@preact/signals-react]
import { signal } from "@preact/signals-react";
const count = signal. Export function Counter() {
return;
}That’s a very different lever compared to “wrap it in memo and hope you didn’t miss a prop that changes every render.” Been there. ---
What shifts in your head as a React dev?
1) Dependency arrays vs automatic tracking
With Hooks, we draw the reactivity map ourselves:
useEffectuseMemouseCallback
Signals tend to flip it. You read a signal inside a tracking context, and it becomes a dependency automatically. Angular’s signals overview lays out this exact idea, signals as getter functions and the framework tracks where they’re used so it can optimize updates. Angular signals overview
This can wipe out a whole class of “oops, missing dep” and “oops, stale closure” bugs. But it can also create a new flavor of mistake: “oops, I read a signal here and subscribed without meaning to.” Not hypothetical. ### 2) “State outside React” stops feeling weird
A lot of React performance work turns into stabilizing references, cutting prop churn, and trying not to accidentally make everything re-render because one object identity changed. Signals lean into a different vibe. Keep state outside components, pass stable signal references around, and let updates jump straight to consumers. Preact’s signals guide says it plainly. When you pass a signal through props or context, you’re passing the signal reference, not a snapshot value. Preact signals guide
3) Effects start to feel less lifecycle-y
React’s useEffect is tied to render/commit. Signals ecosystems often give you primitives that mean “run when dependencies change” such as effect, createEffect, and friends. In Solid, createEffect is a core primitive for reacting to signal changes, and LogRocket covers it in their comparison. LogRocket
Performance: are signals actually faster than Hooks?
In a lot of reactive-heavy cases, yeah. Fine-grained updates can avoid whole-component re-execution and cut down wasted renders. That’s the main sales pitch. But I’d be careful with sweeping claims. Benchmarks bounce around. React can be seriously fast if you build it well. A few points worth keeping on your radar:
The
@preact/signals-reactdocs describe optimizations that can skip virtual DOM rendering entirely in certain cases, like using a signal directly in JSX. @preact/signals-reactThere’s also a Stack Overflow thread where people discuss optimized Hooks vs Preact signals and claim signals can be “faster by default” and avoid vDOM overhead depending on usage. It’s anecdotal, but it lines up with how the model works. Stack Overflow discussion
And React isn’t ignoring this. React’s answer to “manual memoization is tedious” is React Compiler, which aims to automatically memoize and reduce cascading re-renders. The React docs even mention this is sometimes referred to as “fine-grained reactivity.” That’s… a pretty loud hint where things are headed. React Compiler intro
How to try signals in React without lighting your codebase on fire
Use the Babel transform, recommended
@preact/signals-react recommends a Babel transform so components using signals become reactive automatically. ```bash
npm i --save-dev @preact/signals-react-transform
```json
{
"plugins": [["module:@preact/signals-react-transform"]]
}Source: @preact/signals-react
Or opt in per component with useSignals()
If the transform isn’t an option:
import { signal } from "@preact/signals-react". Import { useSignals } from "@preact/signals-react/runtime";
const count = signal(0). Export function Counter() {
useSignals(). Return <p>Count: {count.value}</p>;
}Also straight from the adapter docs. @preact/signals-react
Common mistakes when you mix signals and Hooks
- Accidental subscriptions. Read signals in places you didn’t intend, and suddenly you’ve attached reactivity where you didn’t want it. - SSR assumptions. The React adapter notes SSR rendering like
renderToStringwon’t track signals during render, because there’s no reason to re-render server output. @preact/signals-react - Render props edge cases. The Babel transform can miss signal reads hidden inside render-prop callbacks unless you tweak config. Documented limitation. @preact/signals-react
- Team confusion. If half the codebase thinks in Hooks and the other half thinks in signals, people guess wrong about what triggers updates. And those guesses get expensive. ---
Best practices: what I’d actually do on a real team
I’d keep component-local UI state in Hooks unless signals solve a real pain point. Simple wins. Signals make more sense when you’ve got stuff like shared state turns prop drilling into a part-time job, or lots of small updates like counters, progress, live stats, editors. Those UIs can get chatty fast. And I still prefer derived state as computed in signals land, or useMemo in Hook land, instead of storing duplicates and then babysitting consistency. Profile before you rewrite. Always. If you’re staying in React, React Compiler is worth looking at because it cuts memoization boilerplate. React Compiler intro
Internal link that pairs well with this discussion: if you’re building UI-heavy apps, component choices matter too. See 15 best React UI libraries for 2026. ---
So… signals vs hooks. Who wins?
This isn’t a cage match. It’s a trade. Hooks give you a consistent component-first model with a huge ecosystem. Signals give you more granular reactivity, can reduce unnecessary work, and sometimes make state flows feel weirdly simple once you get used to them. If you’re curious, try signals in one slice of your app. A live-updating widget is perfect. Compare complexity and performance like an adult, not like Twitter. And if you’ve already tried them, I genuinely want to hear what broke first. Leave a comment or share a snippet. ---
Sources
- LogRocket . “Hooks vs. Signals. The great reactivity convergence explained”
https.//blog.logrocket.com/signals-vs-hooks-reactivity-models/ - React Docs ,
useStatereference
https.//react.dev/reference/react/useState - React Docs .
useEffectreference
https.//react.dev/reference/react/useEffect - Preact Docs . Signals guide
https.//preactjs.com/guide/v10/signals/ - npm .
@preact/signals-reactdocumentation (transform,useSignals, optimizations, SSR notes, limitations)
https.//www.npmjs.com/package/@preact/signals-react - Solid Docs — Signals concept documentation
https.//docs.solidjs.com/concepts/signals - Angular Docs — Signals overview (granular tracking, computed laziness/memoization, dynamic deps, untracked)
https.//angular.dev/guide/signals - React Docs — React Compiler introduction (automatic memoization, reducing cascading rerenders)
https.//react.dev/learn/react-compiler/introduction - Stack Overflow — “Comparing Performance. React Hooks with Optimization vs. Preact Signals” (practitioner discussion)
https.//stackoverflow.com/questions/77405932/comparing-performance-react-hooks-with-optimization-vs-preact-signals - DEV Community — “React vs. Signals. The Future of State Management?” (ecosystem framing)
https.//dev.to/mridudixit15/react-vs-signals-the-future-of-state-management-202o - YouTube — “Why Signals Are Better Than React Hooks” (commentary perspective)
https://www.youtube.com/watch?v=SO8lBVWF2Y8 - Reddit — “What Every React Developer Should Know About Signals” (community discussion)
https://www.reddit.com/r/reactjs/comments/1lq0yj7/what_every_react_developer_should_know_about/