Skip to content

Unwrap signals returned from Show's when callback - #975

Closed
marvinhagemeister wants to merge 1 commit into
mainfrom
show-unwrap-signal-from-callback
Closed

Unwrap signals returned from Show's when callback#975
marvinhagemeister wants to merge 1 commit into
mainfrom
show-unwrap-signal-from-callback

Conversation

@marvinhagemeister

Copy link
Copy Markdown
Member

Problem

When Show's when prop is a callback like () => someSignal, the returned Signal object was used directly in the truthiness check. Since Signal objects are always truthy, the fallback branch was never rendered — even when the signal's value was false, 0, ``, or null.

This is inconsistent with the non-callback form when={someSignal}, which already reads .value.

Fix

Unwrap the return value when it's a Signal, reading .value before the truthiness check:

const raw = typeof props.when === "function" ? props.when() : props.when.value;
const value = raw instanceof Signal ? raw.value : raw;

Why this matters

SFC compilers (like @preact-labs/sfc-codegen) emit {#if expr} blocks as <Show when={() => expr}>. When expr is a signal, the callback returns the Signal object. Without unwrapping, {#if falsySignal} would always render the consequent branch instead of the fallback.

When when is a function like () => someSignal, Show used the returned Signal
object directly in its truthiness check. Signal objects are always truthy, so
the fallback branch was never shown — even when the signal's value was falsy.

Show now unwraps the return value when it is a Signal, reading .value before
the truthiness check. This matches the existing behavior for the non-callback
form (when={someSignal}), which already reads .value.

Assisted-By: devx/dca78f42-f55f-4065-b66c-fc3731bd0420
@changeset-bot

changeset-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1fd95f8

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 0 packages

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

Not sure what this means? Click here to learn what changesets are.

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

@netlify

netlify Bot commented Aug 14, 2026

Copy link
Copy Markdown

Deploy Preview for preact-signals-demo ready!

Name Link
🔨 Latest commit 1fd95f8
🔍 Latest deploy log https://app.netlify.com/projects/preact-signals-demo/deploys/6a7f1621031890000866badc
😎 Deploy Preview https://deploy-preview-975--preact-signals-demo.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions

Copy link
Copy Markdown
Contributor

Size Change: +10 B (+0.01%)

Total Size: 199 kB

📦 View Changed
Filename Size Change
docs/dist/assets/devtools-********.js 913 B +2 B (+0.22%)
docs/dist/assets/utils.module-********.js 528 B +8 B (+1.54%)
ℹ️ View Unchanged
Filename Size
docs/dist/assets/bench-********.js 1.6 kB
docs/dist/assets/client-********.js 46.6 kB
docs/dist/assets/EmbeddedDevtools-********.js 23 kB
docs/dist/assets/index-********.js 540 B
docs/dist/assets/jsxRuntime.module-********.js 300 B
docs/dist/assets/preact.module-********.js 4.74 kB
docs/dist/assets/signals-core.module-********.js 1.92 kB
docs/dist/assets/signals.module-********.js 2.66 kB
docs/dist/assets/style-********.css 7.19 kB
docs/dist/assets/Unmount-********.js 651 B
docs/dist/basic-********.js 247 B
docs/dist/nesting-********.js 1.15 kB
docs/dist/react-********.js 242 B
packages/core/dist/signals-core.js 1.94 kB
packages/core/dist/signals-core.mjs 1.93 kB
packages/debug/dist/debug.js 4.72 kB
packages/debug/dist/debug.mjs 4.24 kB
packages/devtools-adapter/dist/devtools-adapter.js 2.36 kB
packages/devtools-adapter/dist/devtools-adapter.mjs 2.07 kB
packages/devtools-ui/dist/devtools-ui.js 21.3 kB
packages/devtools-ui/dist/devtools-ui.mjs 20.6 kB
packages/preact-transform/dist/signals-transform.js 1.66 kB
packages/preact-transform/dist/signals-transform.mjs 1.61 kB
packages/preact-transform/dist/signals-transform.umd.js 1.77 kB
packages/preact/dist/signals.js 1.82 kB
packages/preact/dist/signals.mjs 1.76 kB
packages/react-transform/dist/signals-transform.js 7.63 kB
packages/react-transform/dist/signals-transform.mjs 6.78 kB
packages/react-transform/dist/signals-transform.umd.js 7.75 kB
packages/react/dist/signals.js 214 B
packages/react/dist/signals.mjs 165 B
packages/vite-plugin/dist/vite-plugin.js 8.86 kB
packages/vite-plugin/dist/vite-plugin.mjs 7.86 kB

compressed-size-action

typeof props.when === "function" ? props.when() : props.when.value;
// Unwrap a signal returned by a `when` callback so `when={() => someSignal}`
// checks the signal's value, not the signal object (which is always truthy).
const value =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a big fan of this, this feels like just adding bytes. The callback was intended to be a shortcut to a computed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair point, I'll move that to the SFC compiler

@marvinhagemeister
marvinhagemeister deleted the show-unwrap-signal-from-callback branch August 14, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants