jack
jack
Explore posts from servers
SSolidJS
Created by jack on 8/26/2024 in #support
useSubmission pending state resolves on url change?
i have some optimistic ui, with roughly the following structure:
view = "edit" | "read", based on searchParams
data = fetch data from server
editable = copy of data we can write to (what we render)

when the user clicks save =>
invoke save fn() (which is an action())
**set view -> "read" (rest of ui is already optimistically set)

if no error thrown (via try)
await revalidate() // wan't to make sure we have server state befoe confirming success
toast("good")
if error thrown (via catch)
await revalidate() // reset to good state
toast("bad")

view = "edit" | "read", based on searchParams
data = fetch data from server
editable = copy of data we can write to (what we render)

when the user clicks save =>
invoke save fn() (which is an action())
**set view -> "read" (rest of ui is already optimistically set)

if no error thrown (via try)
await revalidate() // wan't to make sure we have server state befoe confirming success
toast("good")
if error thrown (via catch)
await revalidate() // reset to good state
toast("bad")

then somewhere else i use useSubmission(save) and disable buttons based on pending state as i don't want user's editing lists that aren't accurate to server state. the weird thing is, when i include the logic above with the **, the useSubmission state basically dies. it returns to undefined, and my buttons are don't disabled if instead i wait to set view -> "read" until after i've checked the result of the server call, then the pending state works perfectly (which i can't really do, otherwise the illusion of the optimistic ui is gone) wondering if this is expected, or perhaps i'm doing something wrong? I can post code tomorrow if this doesn't make sense, thanks!
6 replies
SSolidJS
Created by jack on 8/26/2024 in #support
does any sort of primitive similar to Show for non-jsx use exist?
i had Claude generate most of this function for me. wondering if there's a solution/pattern for this problem, as well as if this is a horrible idea and i'm missing some case as to why
export function depends<T, U>(
v: () => T | undefined,
fn: (value: NonNullable<T>) => Promise<U>
): () => Promise<U | undefined> {
return async () => {
const value = v();
if (value !== undefined && value !== null) {
return fn(value as NonNullable<T>);
}
return undefined;
};
}
export function depends<T, U>(
v: () => T | undefined,
fn: (value: NonNullable<T>) => Promise<U>
): () => Promise<U | undefined> {
return async () => {
const value = v();
if (value !== undefined && value !== null) {
return fn(value as NonNullable<T>);
}
return undefined;
};
}
so that i can write signals with async inputs a bit easier:
const selections = createAsync(
depends(
() => user()?.id,
async (userId) => getSelections(userId)
)
);
const selections = createAsync(
depends(
() => user()?.id,
async (userId) => getSelections(userId)
)
);
previously i'd have to either do some sort of type guard/narrow manually each time in the function passed here which isn't great, or I just do like user()?id ?? "", but i don't really want to be passing empty string down as a fallback, i'd rather do nothing until user()?.id is valid
1 replies
SSolidJS
Created by jack on 8/25/2024 in #support
use of cache causing page not to render at all on client nav
been struggling with this for like 2 hours and finally narrowed down that if any single cache() call exists in my file, my page just won't render it's content (at least on client) i have no idea why this is happening, and i'm not really sure at what point this began to happen. wondering if there are any common symptoms for this
4 replies
SSolidJS
Created by jack on 8/25/2024 in #support
derived, but update-able, signal?
is it possible to have a piece of reactive code that can be updated directly, but is also tied to another piece of state? I have a list I fetch from server that is wrapped with createAsync. I want to use this to track server state, but then have a dup of that list that can be updated any number of times in the app. The user then hits save, and we update the list on server and revalidate I originally just tried a derived signal, but I can't directly update this. Then I was thinking of just making another signal and having it's initial value be a call to its initial value, but I'm not sure if this is a good thing to do any idea?
47 replies
SSolidJS
Created by jack on 8/10/2024 in #support
typing Page props ?
is it possible to type the props for the page? I'm tryna to block the page until render, and the best I've come up with is:
const load = cache(
(userId: string) => api.getSelectionsByUserId(userId),
"selections"
);

export const route = {
preload: () => load,
} satisfies RouteDefinition;

export default function Username(props: ManuallyTypePropsAfterLookingAtConsoleLog) {
const selections = createAsync(() => load(users[0].id), {
deferStream: true,
initialValue: props.data,
});
//...
const load = cache(
(userId: string) => api.getSelectionsByUserId(userId),
"selections"
);

export const route = {
preload: () => load,
} satisfies RouteDefinition;

export default function Username(props: ManuallyTypePropsAfterLookingAtConsoleLog) {
const selections = createAsync(() => load(users[0].id), {
deferStream: true,
initialValue: props.data,
});
//...
but the props have to be manually typed
39 replies
SSolidJS
Created by jack on 8/9/2024 in #support
nested layout
is it possible to make the file structure like follows:
- routes
- (user)
- layout.tsx
- [username].tsx
- routes
- (user)
- layout.tsx
- [username].tsx
obviously layout.tsx isn't the proper naming convention, but just wondering if it's possible to achieve something like that. Currently I'm doing
- routes
- (user)
- [username].tsx
- (user).tsx // this is the layout
- routes
- (user)
- [username].tsx
- (user).tsx // this is the layout
but routes/ is gets pretty cluttered fast as I create route groups
3 replies
SSolidJS
Created by jack on 12/22/2023 in #support
type narrowing signals
I've got some state (I'm making a card game) that looks like
type GameInProgress = {
state: "playing" | "paused";
p1Flipped: boolean;
p2Flipped: boolean;
};

type GameOver = {
state: "over";
};

type GamePaused = {
state: "paused";
p1Flipped: true;
p2Flipped: true;
};

type Game = {
state: "playing" | "paused" | "over";
} & (GameInProgress | GamePaused | GameOver);
type GameInProgress = {
state: "playing" | "paused";
p1Flipped: boolean;
p2Flipped: boolean;
};

type GameOver = {
state: "over";
};

type GamePaused = {
state: "paused";
p1Flipped: true;
p2Flipped: true;
};

type Game = {
state: "playing" | "paused" | "over";
} & (GameInProgress | GamePaused | GameOver);
and then my signal to track game state ends up looking like
const [gameState, setGameState] = createSignal<Game>({
state: "over",
});
const [gameState, setGameState] = createSignal<Game>({
state: "over",
});
over time, i want to update this object. since i'm using discriminated types, if i want to reason about any of the props that only exist on GamePaused or GameOver, I need to do some narrowing. it seems like doing a if (gameState().state !== "playing") { return } ... gameState().___ doesn't successfully autocomplete. I'm assuming that typescript doesn't have enough info to guarantee that the 2nd getter invocation will be equivalent to that of the first. Next reasonable idea is to invoke the getter once and store in a variable, then use that to type narrow. But then when I do a setGameState(...) using that variable, I'm not following the nested reactivity pattern here https://www.solidjs.com/tutorial/stores_nested_reactivity Any thoughts/best practices here ?
16 replies