binajmen
binajmen
Explore posts from servers
SSolidJS
Created by binajmen on 7/19/2024 in #support
is it ok to use `action()` to handle form submission in a SPA?
my idea is to handle form submission as follow:
...

const submit = action(async (formData: FormData) => {
const values = Object.fromEntries(formData.entries());
const parsing = projectSchema.safeParse(values);

if (!parsing.success) return parsing.error.flatten();

searchParams.id
? update.mutate({ ...parsing.data, id: searchParams.id })
: create.mutate(parsing.data);
});

const submission = useSubmission(submit);

return (
<Stack>
<h1 class="h1">Project</h1>
<form method="post" action={submit} class={stack()}>
<Input
name="name"
label="Projektbezeichnung"
value={project.data?.name}
error={submission.result?.fieldErrors?.name}
/>
...

const submit = action(async (formData: FormData) => {
const values = Object.fromEntries(formData.entries());
const parsing = projectSchema.safeParse(values);

if (!parsing.success) return parsing.error.flatten();

searchParams.id
? update.mutate({ ...parsing.data, id: searchParams.id })
: create.mutate(parsing.data);
});

const submission = useSubmission(submit);

return (
<Stack>
<h1 class="h1">Project</h1>
<form method="post" action={submit} class={stack()}>
<Input
name="name"
label="Projektbezeichnung"
value={project.data?.name}
error={submission.result?.fieldErrors?.name}
/>
but i'm wondering if there is a side effect i'm unaware of when in SPA mode 🤔 i believe actions were created for the SSR world, but perhaps i'm wrong and this usage is fine.
1 replies
SSolidJS
Created by binajmen on 7/4/2024 in #support
Is there a way to access children props?
Ih this code:
import { render, Dynamic } from "solid-js/web";
import { children, type ParentProps, For, createEffect } from "solid-js";

function App() {
return (
<Editor>
<Line>First line</Line>
<Line onClick={() => console.log("hey!")}>Second line</Line>
</Editor>
);
}

function Editor(props: ParentProps) {
const lines = children(() => props.children);

return (
<ol>
<For each={lines.toArray()}>
{(child, index) => <Dynamic component={Line} number={index() + 1} />}
</For>
</ol>
);
}

function Line(props: ParentProps<{ number?: number; onClick?: () => void }>) {
return (
<div onClick={() => props.onClick}>
{props.number} - {props.children}
</div>
);
}

render(() => <App />, document.getElementById("app")!);
import { render, Dynamic } from "solid-js/web";
import { children, type ParentProps, For, createEffect } from "solid-js";

function App() {
return (
<Editor>
<Line>First line</Line>
<Line onClick={() => console.log("hey!")}>Second line</Line>
</Editor>
);
}

function Editor(props: ParentProps) {
const lines = children(() => props.children);

return (
<ol>
<For each={lines.toArray()}>
{(child, index) => <Dynamic component={Line} number={index() + 1} />}
</For>
</ol>
);
}

function Line(props: ParentProps<{ number?: number; onClick?: () => void }>) {
return (
<div onClick={() => props.onClick}>
{props.number} - {props.children}
</div>
);
}

render(() => <App />, document.getElementById("app")!);
I was hoping to be able to pass the children props to the dynamic component. Is there a way to do this?
45 replies
SSolidJS
Created by binajmen on 6/10/2024 in #support
How to set a new value in a store of `Record<string, __>`?
In the following example: https://playground.solidjs.com/anonymous/07b233f7-59cb-4202-a3ca-595a497912f8 setValue("abc", 3) on a blank object will trigger an error:
Uncaught TypeError: Cannot read properties of undefined (reading 'output')
Uncaught TypeError: Cannot read properties of undefined (reading 'output')
Probably because the internal of the Store's path syntax function is trying to access the data. Am I suppose to use the Immer inspired produce to add a new element to an object, or is there a syntax I don't know to use directly the setter from the store without using produce?
10 replies
SSolidJS
Created by binajmen on 6/6/2024 in #support
Yet another reactivity problem :cry:
Hi, This is a small reproduction of a problem I have with reactivity. https://playground.solidjs.com/anonymous/ea30129e-e6d3-45aa-9345-192095a33f1b My main question is why the DOM is not updated whereas I return from the context a getter function (that should trigger the reactivity, right?) while the data is correctly logged in the console I based myself on this example: https://github.com/solidjs/solid-realworld/blob/f6e77ecd652bf32f0dc9238f291313fd1af7e98b/src/store/index.js#L17-L31
12 replies
SSolidJS
Created by binajmen on 5/20/2024 in #support
How do you delete an entry in an array when using `createStore`
In the following documentation, this case is not presented: https://docs.solidjs.com/guides/complex-state-management It could be trivial but I'm unsure of the right way for doing that 🙏
46 replies
SSolidJS
Created by binajmen on 4/30/2024 in #support
Is this (completely 🫣) illegal in Solid world?
what is the best primitives/library to use when dealing with deep nested structure? the data I'm dealing with looks like a graph with nodes and leaves. every nodes/leaves has a component that should update his data that should stay reactive. pretty hard to explain the context 😅 I was thinking about using a createStore (globally or within a context)
23 replies
SSolidJS
Created by binajmen on 4/26/2024 in #support
Are store reactive?
const [params, setParams] = createStore<Params>(
props.value ?? {
data: [
{ points: 100, requirement: 10 },
{ points: 50, requirement: 5 },
{ points: 0, requirement: 0 },
],
},
);

createEffect(() => {
console.log(params.data.at(0));
});
const [params, setParams] = createStore<Params>(
props.value ?? {
data: [
{ points: 100, requirement: 10 },
{ points: 50, requirement: 5 },
{ points: 0, requirement: 0 },
],
},
);

createEffect(() => {
console.log(params.data.at(0));
});
It consoles several time at rendering, but when modifying the values no more logs
17 replies
SSolidJS
Created by binajmen on 4/20/2024 in #support
Is conditional rendering possible?
I have the following code:
export default function Upsert() {
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const program = getProgram(() => searchParams.id);
const mutation = postProgram(() => {
navigate("/admin/programs");
});

const [, { Form, Field }] = createForm<Program>({
validate: valiForm(programSchema),
initialValues: program.data,
});

return (
<Stack>
<h1 class="h1">Create program</h1>
<Form onSubmit={(values) => mutation.mutate(values)}>
<Stack>
<Field name="name">
{(field, props) => (
<TextField
{...field}
{...props}
label="Name"
error={merge(field, mutation)}
/>
)}
</Field>
<Button type="submit" class="self-start">
Create
</Button>
</Stack>
</Form>
</Stack>
);
}
export default function Upsert() {
const [searchParams] = useSearchParams();
const navigate = useNavigate();
const program = getProgram(() => searchParams.id);
const mutation = postProgram(() => {
navigate("/admin/programs");
});

const [, { Form, Field }] = createForm<Program>({
validate: valiForm(programSchema),
initialValues: program.data,
});

return (
<Stack>
<h1 class="h1">Create program</h1>
<Form onSubmit={(values) => mutation.mutate(values)}>
<Stack>
<Field name="name">
{(field, props) => (
<TextField
{...field}
{...props}
label="Name"
error={merge(field, mutation)}
/>
)}
</Field>
<Button type="submit" class="self-start">
Create
</Button>
</Stack>
</Form>
</Stack>
);
}
getProgram and postProgram are wrappers around solid-query. When accessing the page with an id in the query string (eg. ?id=123) the first time, initialValues equals to undefined as the query is not yet finished and program.data is undefined. Then the query resolved and now program.data is populated, but the form is already rendered so the form does not have any default values. Hitting a second time the same page with the same id will lead to a populated form: the cache is already present so this time program.data is defined. Is it possiple to trigger a re-rendering à la React - (don't shoot me 🙈 ) - to rerun createForm with the actual data? Or should I extract the createForm + <Form /> is a separate component and wrap it with a conditional <Show />?
22 replies
SSolidJS
Created by binajmen on 4/17/2024 in #support
How do you keep reactivity?
I'm trying to organize my code but I lose the reactivity on the way... When the searchParams.id value is set from undefined to a correct string value, I would expect the query to be executed and the effect to be triggered. It is not. If I uncomment the createQuery section instead of using getProgram, it works.
// ~/api/programs.ts
export function getProgram(id?: string) {
return createQuery<Program>(() => ({
queryKey: ["program", id],
queryFn: async () => {
return fetch(`http://localhost:4000/api/programs/${id}`)
.then((res) => res.json())
.then((data) => data.data);
},
enabled: !!id,
}));
}

-------------

import { getProgram, postProgram } from "~/api/programs";

export default function Upsert() {
const [searchParams, setSP] = useSearchParams();
const category = getProgram(searchParams.id);
// const category = createQuery<Program>(() => ({
// queryKey: ["program", searchParams.id],
// queryFn: async () => {
// return fetch(`http://localhost:4000/api/programs/${searchParams.id}`)
// .then((res) => res.json())
// .then((data) => data.data);
// },
// enabled: !!searchParams.id,
// }));

createEffect(() => {
console.log(
category,
category.data,
searchParams.id,
);
});
// ~/api/programs.ts
export function getProgram(id?: string) {
return createQuery<Program>(() => ({
queryKey: ["program", id],
queryFn: async () => {
return fetch(`http://localhost:4000/api/programs/${id}`)
.then((res) => res.json())
.then((data) => data.data);
},
enabled: !!id,
}));
}

-------------

import { getProgram, postProgram } from "~/api/programs";

export default function Upsert() {
const [searchParams, setSP] = useSearchParams();
const category = getProgram(searchParams.id);
// const category = createQuery<Program>(() => ({
// queryKey: ["program", searchParams.id],
// queryFn: async () => {
// return fetch(`http://localhost:4000/api/programs/${searchParams.id}`)
// .then((res) => res.json())
// .then((data) => data.data);
// },
// enabled: !!searchParams.id,
// }));

createEffect(() => {
console.log(
category,
category.data,
searchParams.id,
);
});
11 replies
SSolidJS
Created by binajmen on 4/12/2024 in #support
The props are reactive, right?
I've created a small wrapper around solid-table:
export function DataTable<TData extends { id: string }>(props: {
data: TableOptions<TData>["data"];
columns: TableOptions<TData>["columns"];
}) {
// const [data, setData] = createSignal(props.data);
const table = createSolidTable({
data: props.data,
// data: data(),
columns: props.columns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getRowId: (row) => row.id,
});

createEffect(() => console.log(props.data));

// createEffect(() => setData(props.data));
// createEffect(() => console.log(data()));
export function DataTable<TData extends { id: string }>(props: {
data: TableOptions<TData>["data"];
columns: TableOptions<TData>["columns"];
}) {
// const [data, setData] = createSignal(props.data);
const table = createSolidTable({
data: props.data,
// data: data(),
columns: props.columns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getRowId: (row) => row.id,
});

createEffect(() => console.log(props.data));

// createEffect(() => setData(props.data));
// createEffect(() => console.log(data()));
I use this component within a Suspense. Therefore props.data is equal to [], then populated with data. However, it doesn't seem to trigger an update. I tried to use a signal in the middle to make it reactive (see the comments) even if props.data is already reactive. The effects are triggered and logging the data, but the table remains empty 🤔
21 replies
SSolidJS
Created by binajmen on 4/11/2024 in #support
Am I obliged to combine Suspense with Show?
I get the following error: Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'map') I understand the cause, but I'm surprised. I was expecting that the Suspense would delay the children until the data is available. Adding a Show solves the issue, but I'm wondering if I can handle this differently.
import { createQuery } from "@tanstack/solid-query";
import { Suspense } from "solid-js";

type Program = {
id: string;
name: string;
};

export default function List() {
const categories = createQuery<Program[]>(() => ({
queryKey: ["programs"],
queryFn: async () => {
return fetch("http://localhost:4000/api/programs")
.then((res) => res.json())
.then((data) => data.data);
},
}));

return (
<div>
<h1>Programs</h1>
<Suspense fallback={<p>Loading...</p>}>
{JSON.stringify(categories.data!.map((c) => c.name))}
</Suspense>
</div>
);
}
import { createQuery } from "@tanstack/solid-query";
import { Suspense } from "solid-js";

type Program = {
id: string;
name: string;
};

export default function List() {
const categories = createQuery<Program[]>(() => ({
queryKey: ["programs"],
queryFn: async () => {
return fetch("http://localhost:4000/api/programs")
.then((res) => res.json())
.then((data) => data.data);
},
}));

return (
<div>
<h1>Programs</h1>
<Suspense fallback={<p>Loading...</p>}>
{JSON.stringify(categories.data!.map((c) => c.name))}
</Suspense>
</div>
);
}
22 replies
DTDrizzle Team
Created by binajmen on 3/19/2024 in #help
Store percentage value as integer
Hi, I realised once again how awesome Drizzle is! I want to store percentage value as integer. I ended up with this:
export const percentage = customType<{ data: number, driverData: number }>({
dataType() {
return 'integer'
},
toDriver(value: number) {
return Math.round(value * 100)
},
fromDriver(value: number) {
return value / 100
}
})
export const percentage = customType<{ data: number, driverData: number }>({
dataType() {
return 'integer'
},
toDriver(value: number) {
return Math.round(value * 100)
},
fromDriver(value: number) {
return value / 100
}
})
For my use case, it is correct as I don't want to store more than 2 decimals. Using the type decimal is inconvenient as it is stored as string with the Postgres driver. Hence this choice. But my question is about the caveats of this technique. Does the in & out conversion affect the performance in a noticeable way?
3 replies
SSolidJS
Created by binajmen on 2/14/2024 in #support
ReferenceError on something that should (and DO) exist
tl;dr: getting a reference error on an existing (declared and in scope) variable:
categories.tsx:33 Uncaught ReferenceError: categories is not defined
at get when (categories.tsx:33:20)
at Switch.createMemo.equals.equals [as fn] (chunk-DIOA272S.js?v=36072530:1608:28)
at runComputation (chunk-DIOA272S.js?v=36072530:800:22)
at updateComputation (chunk-DIOA272S.js?v=36072530:782:3)
at createMemo (chunk-DIOA272S.js?v=36072530:344:10)
at Switch (chunk-DIOA272S.js?v=36072530:1604:22)
at chunk-DIOA272S.js?v=36072530:647:12
at untrack (chunk-DIOA272S.js?v=36072530:536:12)
at Object.fn (chunk-DIOA272S.js?v=36072530:643:37)
at runComputation (chunk-DIOA272S.js?v=36072530:800:22)
categories.tsx:33 Uncaught ReferenceError: categories is not defined
at get when (categories.tsx:33:20)
at Switch.createMemo.equals.equals [as fn] (chunk-DIOA272S.js?v=36072530:1608:28)
at runComputation (chunk-DIOA272S.js?v=36072530:800:22)
at updateComputation (chunk-DIOA272S.js?v=36072530:782:3)
at createMemo (chunk-DIOA272S.js?v=36072530:344:10)
at Switch (chunk-DIOA272S.js?v=36072530:1604:22)
at chunk-DIOA272S.js?v=36072530:647:12
at untrack (chunk-DIOA272S.js?v=36072530:536:12)
at Object.fn (chunk-DIOA272S.js?v=36072530:643:37)
at runComputation (chunk-DIOA272S.js?v=36072530:800:22)
The best is to check this reproductible example: https://stackblitz.com/github/binajmen/budget?file=src%2Fpages%2Fcategories.tsx I'm pretty sure I'm doing something wrong, but I can't figure out what..
2 replies
SSolidJS
Created by binajmen on 1/5/2024 in #support
How to Inform children of the active status of it's parent <A/>
I'm looking at something like:
<A href=".." class=".." activeClass="..">
{({ active }) =>
<span classList={{ "my-class": active }}>..</span>
}
</A>
<A href=".." class=".." activeClass="..">
{({ active }) =>
<span classList={{ "my-class": active }}>..</span>
}
</A>
3 replies
DTDrizzle Team
Created by binajmen on 11/29/2023 in #help
`.orderBy` influence `sql` output
With the following code:
const exchanges = await db
.select({
...getTableColumns(stockExchanges),
isUsed:
sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`.mapWith(
(value) => value === "1",
),
})
.from(stockExchanges)
.leftJoin(usedExchanges, eq(usedExchanges.data, stockExchanges.code));

console.log(exchanges.find((exch) => exch.code === "BR"));

const orderedExchanges = await db
.select({
...getTableColumns(stockExchanges),
isUsed:
sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`.mapWith(
(value) => value === "1",
),
})
.from(stockExchanges)
.leftJoin(usedExchanges, eq(usedExchanges.data, stockExchanges.code))
.orderBy(asc(stockExchanges.name));

console.log(orderedExchanges.find((exch) => exch.code === "BR"));
const exchanges = await db
.select({
...getTableColumns(stockExchanges),
isUsed:
sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`.mapWith(
(value) => value === "1",
),
})
.from(stockExchanges)
.leftJoin(usedExchanges, eq(usedExchanges.data, stockExchanges.code));

console.log(exchanges.find((exch) => exch.code === "BR"));

const orderedExchanges = await db
.select({
...getTableColumns(stockExchanges),
isUsed:
sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`.mapWith(
(value) => value === "1",
),
})
.from(stockExchanges)
.leftJoin(usedExchanges, eq(usedExchanges.data, stockExchanges.code))
.orderBy(asc(stockExchanges.name));

console.log(orderedExchanges.find((exch) => exch.code === "BR"));
I get the following output:
{
name: 'Euronext Brussels',
code: 'BR',
operatingMIC: 'XBRU',
country: 'Belgium',
currency: 'EUR',
countryISO2: 'BE',
countryISO3: 'BEL',
isUsed: true
}
{
name: 'Euronext Brussels',
code: 'BR',
operatingMIC: 'XBRU',
country: 'Belgium',
currency: 'EUR',
countryISO2: 'BE',
countryISO3: 'BEL',
isUsed: false
}
{
name: 'Euronext Brussels',
code: 'BR',
operatingMIC: 'XBRU',
country: 'Belgium',
currency: 'EUR',
countryISO2: 'BE',
countryISO3: 'BEL',
isUsed: true
}
{
name: 'Euronext Brussels',
code: 'BR',
operatingMIC: 'XBRU',
country: 'Belgium',
currency: 'EUR',
countryISO2: 'BE',
countryISO3: 'BEL',
isUsed: false
}
Why would the orderBy influence the computed column isUsed (the expected result is true)?
9 replies
DTDrizzle Team
Created by binajmen on 11/28/2023 in #help
Why is 1 and 0 are returned as string?
With the following:
isUsed: sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`
isUsed: sql<boolean>`case when ${usedExchanges.data} is not null then 1 else 0 end`
I get isUsed as "1" or "0" whereas I would expect a boolean.
33 replies
SSolidJS
Created by binajmen on 10/3/2023 in #support
How to choose between Store and Context?
I've gathered that a store can reside in its own file and be imported in multiple locations, acting as a shared state. Given this, why would I opt for a context when a store seems capable of handling the task? Whether it's for theming or authentication status, a store seems apt. Is there an advantage to using a context, or some trade-offs or crucial factors I might be overlooking?
4 replies
SSolidJS
Created by binajmen on 9/29/2023 in #support
How do you consume server actions response?
It might look as a silly question, but it is unclear for me how you must consume the response (either is it result or error).
export default function Users() {
const users = useRouteData<typeof routeData>();

const [creating, { Form }] = createServerAction$(
async (formData: FormData) => {
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
const email = String(formData.get("email"));

if (email.length < 10) {
return json({ success: false, fields: { email: "too small" } }); // <-- will end up in result
// throw json({ success: false, fields: { email: "too small" } }); // <-- will end up in error
}

await db.insert(usersTable).values({ email });

return json({ success: true });
}
);

createEffect(() => console.log("effect:", creating, creating.pending));
console.log(creating);

return (
<div>
<h1>Users list</h1>
<ul>
<For each={users()}>{(user) => <li>{user.email}</li>}</For>
</ul>
<Form>
<label for="email">Email:</label>
<input type="email" name="email" />
<Show when={creating.error}>Error: {creating.error/*???*/}</Show>
<input type="submit" value="submit" />
</Form>
</div>
);
}
export default function Users() {
const users = useRouteData<typeof routeData>();

const [creating, { Form }] = createServerAction$(
async (formData: FormData) => {
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
const email = String(formData.get("email"));

if (email.length < 10) {
return json({ success: false, fields: { email: "too small" } }); // <-- will end up in result
// throw json({ success: false, fields: { email: "too small" } }); // <-- will end up in error
}

await db.insert(usersTable).values({ email });

return json({ success: true });
}
);

createEffect(() => console.log("effect:", creating, creating.pending));
console.log(creating);

return (
<div>
<h1>Users list</h1>
<ul>
<For each={users()}>{(user) => <li>{user.email}</li>}</For>
</ul>
<Form>
<label for="email">Email:</label>
<input type="email" name="email" />
<Show when={creating.error}>Error: {creating.error/*???*/}</Show>
<input type="submit" value="submit" />
</Form>
</div>
);
}
If the action failed (form validation, db error, etc.), I'd like to retrieve this info in the response. In the network tab, the result as the type Response (it makes sense). However, how am I suppose to consume the response and extract the JSON I'm sending from the action?
4 replies
DTDrizzle Team
Created by binajmen on 8/7/2023 in #help
Is it possible to have nested values when doing a leftJoin?
// returns nested results
export async function getLoans(spaceId: string) {
return db.query.loans.findMany({
where: eq(loans.spaceId, spaceId),
with: {
property: true,
financialInstitution: true,
},
});
}

// doesn't return nested results
export async function getLoansLJ(spaceId: string) {
return db
.select()
.from(loans)
.leftJoin(
financialInstitutions,
eq(financialInstitutions.id, loans.financialInstitutionId)
)
.where(eq(loans.spaceId, spaceId));
}
// returns nested results
export async function getLoans(spaceId: string) {
return db.query.loans.findMany({
where: eq(loans.spaceId, spaceId),
with: {
property: true,
financialInstitution: true,
},
});
}

// doesn't return nested results
export async function getLoansLJ(spaceId: string) {
return db
.select()
.from(loans)
.leftJoin(
financialInstitutions,
eq(financialInstitutions.id, loans.financialInstitutionId)
)
.where(eq(loans.spaceId, spaceId));
}
If not, what is your approach when you're not using the query builder? Should I map the results and enrich them based on the financialInstitutionId? Or is there something I missed?
33 replies