#Passing "up" signals in Solid

7 messages · Page 1 of 1 (latest)

thorny snow
#

I am trying to understand how can you go by reading values from signals defined in children components in SolidJS.

I exemplified my situation in the code bellow (with a solution that I came up with but don’t know if is ideal):
I have one component that handles the content being edited (RecordEditor). The submission of the content written by the user is supposed to happens up in the hierarchy, in the AddRecordModal component. That means I need to “access the signals on the children component”.

function AddRecordModal(props: Props) {
    const [title, setTitle] = createSignal<string>("");
    const [amount, setAmount] = createSignal<number>();

    createEffect(() => {
        console.log(title(), amount());
    });

    return (
        <div>
            <RecordEditor class={styles.content} title={[title, setTitle]} amount={[amount, setAmount]} />
            <button onClick={() => console.log(title(), amount())}>Submit record</button>
        </div>
    );
}

function RecordEditor(props: {
    class?: string;
    title: [Accessor<string>, Setter<string>];
    amount: [Accessor<string | number | undefined>, Setter<number | undefined>];
}) {
    const [title, setTitle] = props.title || createSignal<string>();
    const [amount, setAmount] = props.amount || createSignal<number>();

    return (
        <div class={clsx(styles.container, props.class)}>
            <input type="text" placeholder="Title" value={title()} onInput={(e) => setTitle(e.currentTarget.value)} />
            <input
                type="number"
                placeholder="Amount"
                value={amount()}
                onInput={(e) => setAmount(parseFloat(e.currentTarget.value))}
            />
        </div>
    );
}
still vault
#

Either make the signal global, in a context or in the parent component

tidal bone
thorny snow
#

Since those two components are directly in contact, I think context would be too much in this case so I wanted to find if there a less complex route

tidal bone
# thorny snow Ok! Thank you so much for the examples, that was what I was needing the most! I ...

Instead of title: [Accessor<string>, Setter<string>]; we set 2/3 props:

title: string;
defaultTitle: string;
onTitleChange: Setter<string>;

then used as:

const [title, setTitle] = createControllableSignal({
    defaultValue: () => props.defaultTitle ?? "other default",
    onChange: props.onTitleChange,
    value: () => props.title,
});

title() // string
setTitle("updated title")

parent component:

const [title, setTitle] = createSignal<string>("");
<RecordEditor title={title} onTitleChange={setTitle} />
// or
<RecordEditor defaultTitle="default title controlled entirely by subcomponent" />
thorny snow
#

Ohh, ok!!