S
SolidJS•3mo ago
Jess

Ternary and Show have unequal output

In a basic Vite and Solid app, I have
const [page, setPage] = createSignal({
image: null,
timer: null,
choices: [],
notifications: [],
prompting: false,
awaiting_confirm: false,
} as Page, { equals: false })
// Some time later

{page().prompting ? <input type="text" value={promptInput()} onInput={(e) => setPromptInput(e.currentTarget.value)} onKeyPress={(event) => {
if (event.key === "Enter") {
engine.setPromptResponse(promptInput());
setPromptInput("");
}
}} /> : <></>}

<Show when={() => page().prompting}>
<p>I shouldn't be here</p>
</Show>
const [page, setPage] = createSignal({
image: null,
timer: null,
choices: [],
notifications: [],
prompting: false,
awaiting_confirm: false,
} as Page, { equals: false })
// Some time later

{page().prompting ? <input type="text" value={promptInput()} onInput={(e) => setPromptInput(e.currentTarget.value)} onKeyPress={(event) => {
if (event.key === "Enter") {
engine.setPromptResponse(promptInput());
setPromptInput("");
}
}} /> : <></>}

<Show when={() => page().prompting}>
<p>I shouldn't be here</p>
</Show>
But, "I shouldn't be here" is showing up, while the input (which was originally in place of the "I shouldn't be here") doesn't, as expected. Am I misunderstanding the When component or is it just interacting strangely? It hides the text when I put in a straight false, but not when I use a false reactive signal
26 Replies
Jess
Jess•3mo ago
Although, later on,
<Show when={() => page().awaiting_confirm}>
<button onClick={() => engine.clearAwaitingConfirm()}>Continue</button>
</Show>
<Show when={() => page().awaiting_confirm}>
<button onClick={() => engine.clearAwaitingConfirm()}>Continue</button>
</Show>
Works just fine I lied, it kinda doesn't work just fine
REEEEE
REEEEE•3mo ago
you don't need to make the when a function
Jess
Jess•3mo ago
It's just as broken when it's not a function, for some reason Always gone when it's not and always there when it is
REEEEE
REEEEE•3mo ago
well prompting is false initially so it won't show the text until you set it to true if it's a function then it'll always resolve to true because there's a value
<Show when={page().prompting}>
<p>I shouldn't be here</p>
</Show>
<Show when={page().prompting}>
<p>I shouldn't be here</p>
</Show>
Should work fine
Jess
Jess•3mo ago
I have a setInterval that ticks the wasm that drives the page object, and I can see in the logs that prompting is true
REEEEE
REEEEE•3mo ago
hmmm I don't really see any other reason for this to not work though 🤔 Could you try with a store?
Jess
Jess•3mo ago
That didn't change anything
const [page, setPage] = createStore({
image: null,
timer: null,
choices: [],
notifications: [],
prompting: false,
awaiting_confirm: false,
} as Page)
// snip

{page.awaiting_confirm ? <p>I'm awaiting confirm</p> : <p>I'm not awaiting confirm</p>}
<br />
<Show when={page.awaiting_confirm}>
<button onClick={() => engine.clearAwaitingConfirm()}>Continue</button>
</Show>
const [page, setPage] = createStore({
image: null,
timer: null,
choices: [],
notifications: [],
prompting: false,
awaiting_confirm: false,
} as Page)
// snip

{page.awaiting_confirm ? <p>I'm awaiting confirm</p> : <p>I'm not awaiting confirm</p>}
<br />
<Show when={page.awaiting_confirm}>
<button onClick={() => engine.clearAwaitingConfirm()}>Continue</button>
</Show>
Shows no "Continue" and shows "I'm not awaiting confirm"
REEEEE
REEEEE•3mo ago
hmmm and this is after it's set to true? so weird is it possible for you to make a repro on stackblitz or the playground?
Jess
Jess•2mo ago
I'll check It seems it isn't solid After some more fiddling I've got
Page JSON {"image":"daf01c05298d2520430802e452378e8733dfaadc","timer":null,"choices":[],"notifications":[],"prompting":false,"awaiting_comfirm":true}
Awaiting confirm false, prompting false
Page JSON {"image":"daf01c05298d2520430802e452378e8733dfaadc","timer":null,"choices":[],"notifications":[],"prompting":false,"awaiting_comfirm":true}
Awaiting confirm false, prompting false
from
setInterval(() => {
engine.tick(BigInt(250));
const pageJson = engine.renderPage();
console.log(`Page JSON ${pageJson}`);
setPage(JSON.parse(pageJson));
console.log(`Awaiting confirm ${page.awaiting_confirm}, prompting ${page.prompting}`);
}, 250);
setInterval(() => {
engine.tick(BigInt(250));
const pageJson = engine.renderPage();
console.log(`Page JSON ${pageJson}`);
setPage(JSON.parse(pageJson));
console.log(`Awaiting confirm ${page.awaiting_confirm}, prompting ${page.prompting}`);
}, 250);
A really basic repro works fine
import { createStore } from "solid-js/store";
import { render } from "solid-js/web";
import { Show, onMount, onCleanup } from "solid-js";

function Counter() {
const [meta, setMeta] = createStore({ nested: false });

let interval: number;
onMount(() => {
interval = setInterval(() => {
if (meta.nested) {
setMeta(JSON.parse('{"nested": false}'));
} else {
setMeta(JSON.parse('{"nested": true}'));
}
}, 2500);
});

onCleanup(() => clearInterval(interval));

return (
<Show when={meta.nested}>
<p>Some text</p>
</Show>
);
}

render(() => <Counter />, document.getElementById("app")!);
import { createStore } from "solid-js/store";
import { render } from "solid-js/web";
import { Show, onMount, onCleanup } from "solid-js";

function Counter() {
const [meta, setMeta] = createStore({ nested: false });

let interval: number;
onMount(() => {
interval = setInterval(() => {
if (meta.nested) {
setMeta(JSON.parse('{"nested": false}'));
} else {
setMeta(JSON.parse('{"nested": true}'));
}
}, 2500);
});

onCleanup(() => clearInterval(interval));

return (
<Show when={meta.nested}>
<p>Some text</p>
</Show>
);
}

render(() => <Counter />, document.getElementById("app")!);
I've come to the conclusion I'm cursed
engine.tick(BigInt(250));
const pageJson = engine.renderPage();
console.log(`Page JSON ${pageJson}`);
const pageParsed = JSON.parse(pageJson) as Page;
console.log("Parsed page", pageParsed);
setPage(pageParsed);
console.log("Stored page", {...page});
console.log(`Prompting ${page.prompting}, Awaiting confirm: ${page.awaiting_confirm}`);
engine.tick(BigInt(250));
const pageJson = engine.renderPage();
console.log(`Page JSON ${pageJson}`);
const pageParsed = JSON.parse(pageJson) as Page;
console.log("Parsed page", pageParsed);
setPage(pageParsed);
console.log("Stored page", {...page});
console.log(`Prompting ${page.prompting}, Awaiting confirm: ${page.awaiting_confirm}`);
Page JSON {"image":"daf01c05298d2520430802e452378e8733dfaadc","timer":null,"choices":[],"notifications":[],"prompting":false,"awaiting_comfirm":true}
Parsed page
Object { image: "daf01c05298d2520430802e452378e8733dfaadc", timer: null, choices: [], notifications: [], prompting: false, awaiting_comfirm: true }
Stored page
Object { image: "daf01c05298d2520430802e452378e8733dfaadc", timer: null, choices: Proxy, notifications: Proxy, prompting: false, awaiting_confirm: false, awaiting_comfirm: true }
Prompting false, Awaiting confirm: false App.tsx:60:14
Page JSON {"image":"daf01c05298d2520430802e452378e8733dfaadc","timer":null,"choices":[],"notifications":[],"prompting":false,"awaiting_comfirm":true}
Parsed page
Object { image: "daf01c05298d2520430802e452378e8733dfaadc", timer: null, choices: [], notifications: [], prompting: false, awaiting_comfirm: true }
Stored page
Object { image: "daf01c05298d2520430802e452378e8733dfaadc", timer: null, choices: Proxy, notifications: Proxy, prompting: false, awaiting_confirm: false, awaiting_comfirm: true }
Prompting false, Awaiting confirm: false App.tsx:60:14
REEEEE
REEEEE•2mo ago
if you're still using a store, try using reconcile when setting setPage(reconcile(pageParsed))
Jess
Jess•2mo ago
It now properly updates the page, but it's saying awaiting_confirm is undefined when I try to access it?
Page JSON {"image":"daf01c05298d2520430802e452378e8733dfaadc","timer":null,"choices":[],"notifications":[],"prompting":false,"awaiting_comfirm":true}
Parsed page
Object { image: "daf01c05298d2520430802e452378e8733dfaadc", timer: null, choices: [], notifications: [], prompting: false, awaiting_comfirm: true }
Stored page
Object { image: "daf01c05298d2520430802e452378e8733dfaadc", timer: null, choices: Proxy, notifications: Proxy, prompting: false, awaiting_comfirm: true }
Prompting false, Awaiting confirm: undefined
Page JSON {"image":"daf01c05298d2520430802e452378e8733dfaadc","timer":null,"choices":[],"notifications":[],"prompting":false,"awaiting_comfirm":true}
Parsed page
Object { image: "daf01c05298d2520430802e452378e8733dfaadc", timer: null, choices: [], notifications: [], prompting: false, awaiting_comfirm: true }
Stored page
Object { image: "daf01c05298d2520430802e452378e8733dfaadc", timer: null, choices: Proxy, notifications: Proxy, prompting: false, awaiting_comfirm: true }
Prompting false, Awaiting confirm: undefined
Thank you for being patient, by the way. I always end up invoking demons in the strangest ways
REEEEE
REEEEE•2mo ago
No problem, this is an interesting issue mmm maybe reconcile is failing somehow well, it is setting the store but I think it might not be merging correctly 🤔 Unless something else is changing awaiting_confirm later down the line btw is this an ecs?
Jess
Jess•2mo ago
It's more of a really poorly made interpreter Also, the page store is only modified in the setInterval
REEEEE
REEEEE•2mo ago
It's interesting that the signal version doesn't work even with {equals: false} could you try
setPage(reconcile(pageParsed, {merge: true))
setPage(reconcile(pageParsed, {merge: true))
Jess
Jess•2mo ago
Same behaviour, sadly
No description
REEEEE
REEEEE•2mo ago
if you try printing the store via JSON.stringify rather than {...page}, what do you get?
Jess
Jess•2mo ago
It shows the same JSON as the input to JSON.parse, {"image":"daf01c05298d2520430802e452378e8733dfaadc","timer":null,"choices":[],"notifications":[],"prompting":false,"awaiting_comfirm":true}
REEEEE
REEEEE•2mo ago
I am confused Does the pageJson ever change?
Jess
Jess•2mo ago
Yes The engine will return a different JSON string depending on what runs (backgrounds, prompts/choices, etc.)
REEEEE
REEEEE•2mo ago
Does it ever not contain awaiting_confirm?
Jess
Jess•2mo ago
All keys are guaranteed to exist, only image and timers may be null Well, I found the issue
REEEEE
REEEEE•2mo ago
👀
Jess
Jess•2mo ago
I had a typo in the WASM module that named the field awaiting_comfirm instead of awaiting_confirm
REEEEE
REEEEE•2mo ago
oh okay that's what i figured but I couldn't see it 🤣 my brain glossed over that
Jess
Jess•2mo ago
Why did we have to make the funny double n letter Well, thank you for all your help xd
REEEEE
REEEEE•2mo ago
no problem, glad your issue has been resolved and we've learned to pay closer attention to n and m's