Fix null handling in controllable signal

This commit is contained in:
Mats Bosson 2026-03-29 02:40:38 +07:00
parent 8f2e6042ea
commit 512eba474a

View File

@ -3,7 +3,7 @@ import { type Accessor, createSignal } from "solid-js";
export interface CreateControllableSignalOptions<T> { export interface CreateControllableSignalOptions<T> {
/** Returns the controlled value, or undefined if uncontrolled. */ /** Returns the controlled value, or undefined if uncontrolled. */
value: Accessor<T | undefined>; value: Accessor<T | undefined>;
/** Default value used when uncontrolled. */ /** Default value used when uncontrolled. Only read once at creation time — not reactive after mount. */
defaultValue: Accessor<T>; defaultValue: Accessor<T>;
/** Called whenever the value changes (both modes). */ /** Called whenever the value changes (both modes). */
onChange?: (value: T) => void; onChange?: (value: T) => void;
@ -21,12 +21,14 @@ export function createControllableSignal<T>(
const get: Accessor<T> = () => { const get: Accessor<T> = () => {
const controlled = options.value(); const controlled = options.value();
return controlled !== undefined ? controlled : internalValue(); if (controlled !== undefined) return controlled;
return internalValue();
}; };
const set = (value: T) => { const set = (value: T) => {
const isControlled = options.value() !== undefined; const isControlled = options.value() !== undefined;
if (!isControlled) { if (!isControlled) {
// Use functional form so SolidJS does not interpret T-as-function as an updater.
setInternalValue(() => value); setInternalValue(() => value);
} }
options.onChange?.(value); options.onChange?.(value);