ChrisThornham
ChrisThornham
SSolidJS
Created by ChrisThornham on 7/1/2024 in #support
Is My Understanding Of RouteSectionProps Correct?
I’ve been trying to implement the cache, load, and createAsync pattern on all of my pages that load data. My goal is to load data on hover before navigating to the page. When the cache function does not need a route parameter, this pattern works as expected. BUT, I struggled to get this pattern working when I needed to pass my cache function a route param. After reading through the docs, I "thought" that I should use the useParams() primitive to get the route params, then pass that route param to the function inside of createAsync(). That didn't work. I dug through the HackerNews example and noticed the use of RouteSectionProps. With RouteSectionProps it does work. So... I want to make sure I understand WHY these two examples differ. When using useParams() I'm guessing that you only get access to the route params AFTER the component loads... meaning the params aren't available on hover. But, when using RouteSectionProps it appears that you get access to the route params BEFORE the component loads... which is why load on hover works. Am I correct? Here's my final implementation.
const getUser = cache(async (email: string): Promise<User> => {
"use server";
const { data, error } = await supabase
.from("users")
.select()
.eq("customer_email", email)
.single();

if (error) {
console.log(error.message);
throw error;
}

return data as User;
}, "user");

export const route: RouteDefinition = {
load({ params }) {
void getUser(params.email);
},
};

export default function UserDetailsPage(props: RouteSectionProps) {
const user = createAsync(() => getUser(props.params.email));
...
}
const getUser = cache(async (email: string): Promise<User> => {
"use server";
const { data, error } = await supabase
.from("users")
.select()
.eq("customer_email", email)
.single();

if (error) {
console.log(error.message);
throw error;
}

return data as User;
}, "user");

export const route: RouteDefinition = {
load({ params }) {
void getUser(params.email);
},
};

export default function UserDetailsPage(props: RouteSectionProps) {
const user = createAsync(() => getUser(props.params.email));
...
}
9 replies
SSolidJS
Created by ChrisThornham on 6/30/2024 in #support
Help Me Solve "undefined" warning When Using <Show> Component
I'm using createAsync() to get and order record.
const order = createAsync(() => getOrder(params.chargeId));
const order = createAsync(() => getOrder(params.chargeId));
order has the following type: const order: Accessor<Order | undefined> Because order could be undefined, I must check for that in my jsx. I'm trying to do that with <Show when={order()}> I thought adding the when={order()} would return false if order() was undefined, and satisfy typescript, but typescript is still complaining with this message:
Type 'Accessor<Order | undefined>' is not assignable to type 'Accessor<Order>'
Type 'Accessor<Order | undefined>' is not assignable to type 'Accessor<Order>'
So, how can I get rid of this "undefined" error? I'm trying to do this "the solid way," and I can't figure it out. I get the undefined error when trying to pass the order to a component like this: <OrderTable order={order} /> Here's the full component for context.
import { Order } from "~/types/order";
// CACHE ============================================================
const getOrder = cache(async (chargeId: string) => {
"use server";
const { data } = await supabase
.from("orders")
.select()
.eq("stripe_charge_id", chargeId)
.single();
if (!data) {
return undefined;
} else {
return data as Order;
}
}, "order");

export default function OrderDetailsPage() {
const params = useParams();
const order = createAsync(() => getOrder(params.chargeId));
return (
<>
<h4>Order Details</h4>
<Show when={order()} fallback="Order loading...">
<OrderTable order={order} />
</Show>
</>
);
}
import { Order } from "~/types/order";
// CACHE ============================================================
const getOrder = cache(async (chargeId: string) => {
"use server";
const { data } = await supabase
.from("orders")
.select()
.eq("stripe_charge_id", chargeId)
.single();
if (!data) {
return undefined;
} else {
return data as Order;
}
}, "order");

export default function OrderDetailsPage() {
const params = useParams();
const order = createAsync(() => getOrder(params.chargeId));
return (
<>
<h4>Order Details</h4>
<Show when={order()} fallback="Order loading...">
<OrderTable order={order} />
</Show>
</>
);
}
3 replies
SSolidJS
Created by ChrisThornham on 6/13/2024 in #support
What Replaced createRouteData?
In older version of SolidStart you could get all routes in a folder. This was useful for doing things like getting all blog articles. It worked like this:
export const routeData = () => {
return createRouteData(async () => {
const files = import.meta.glob('.blog/*.mdx')
})
}
export const routeData = () => {
return createRouteData(async () => {
const files = import.meta.glob('.blog/*.mdx')
})
}
But createRouteData no longer exists in the latest version of SolidStart. How could I do the same thing with the newest version of SolidStart? Thanks, Chris
5 replies
SSolidJS
Created by ChrisThornham on 6/5/2024 in #support
Is It Possible To Pass An Extra Parameter To A Form Action?
I'm trying to do this:
const userId = getUserId();

return (
<form action={deleteUser(userId) method="post">
<button>Delete User</button>
</form>
);
const userId = getUserId();

return (
<form action={deleteUser(userId) method="post">
<button>Delete User</button>
</form>
);
Here's the action:
export const deleteUser = action(async (userId: string) => {
await auth.deleteAccount(userId);
});
export const deleteUser = action(async (userId: string) => {
await auth.deleteAccount(userId);
});
I keep getting the following errors on the "action" of the form: Type 'Action<[userId: string], void>' is not assignable to type 'string | SerializableAttributeValue | undefined'.ts(2322) The expected type comes from property 'action' which is declared here on type 'FormHTMLAttributes<HTMLFormElement>' (property) JSX.FormHTMLAttributes<HTMLFormElement>.action?: string | JSX.SerializableAttributeValue | undefined
5 replies
SSolidJS
Created by ChrisThornham on 5/21/2024 in #support
Trouble With onCleanup()
I'm building a checkout flow with Stripe's embedded checkout form. It works like this. The user clicks a "Buy Now" button on a products page that navigates to a checkout page. The checkout page: - Gets the product ID and quantity from the search params. - Gets the checkout form from stripe - Mounts the checkout form. This works the first time I click a buy now button. BUT If I click back to the products page and click another buy now button, the checkout form doesn't load. I'm getting an error from Stripe: "You cannot have multiple embedded checkout items." So, how do I "clear" or unmount the checkout form when I click the back button? I want to start fresh each time I click a buy now button. My use of onCleanup (below) isn't working. Here's my checkout page:
export default function CheckoutPage() {

const [searchParams] = useSearchParams();

// ref
let checkoutElement: HTMLDivElement;

createEffect(async () => {
// extract the search params
const itemsArray = [
{
price: searchParams.priceId,
quantity: searchParams.qty,
},
];

// Stripe Stuff
// Create a checkout session
const response = await fetch("api/stripe/create-checkout-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
items: itemsArray,
}),
});

// Create checkout form
const { clientSecret } = await response.json();
const checkout = await stripe?.initEmbeddedCheckout({
clientSecret,
});

// Mount form
if (checkoutElement) {
checkout?.mount(checkoutElement);
}

// unmount the form
onCleanup(() => {
checkout?.unmount();
});
});

return (
<MainLayout>
<div
id="checkout"
ref={(el) => checkoutElement = el}
class="px-6 py-20 bg-[#0f151d]"
>
{/* Checkout will insert payment form here */}
</div>
</MainLayout>
);
}
export default function CheckoutPage() {

const [searchParams] = useSearchParams();

// ref
let checkoutElement: HTMLDivElement;

createEffect(async () => {
// extract the search params
const itemsArray = [
{
price: searchParams.priceId,
quantity: searchParams.qty,
},
];

// Stripe Stuff
// Create a checkout session
const response = await fetch("api/stripe/create-checkout-session", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
items: itemsArray,
}),
});

// Create checkout form
const { clientSecret } = await response.json();
const checkout = await stripe?.initEmbeddedCheckout({
clientSecret,
});

// Mount form
if (checkoutElement) {
checkout?.mount(checkoutElement);
}

// unmount the form
onCleanup(() => {
checkout?.unmount();
});
});

return (
<MainLayout>
<div
id="checkout"
ref={(el) => checkoutElement = el}
class="px-6 py-20 bg-[#0f151d]"
>
{/* Checkout will insert payment form here */}
</div>
</MainLayout>
);
}
30 replies
SSolidJS
Created by ChrisThornham on 5/13/2024 in #support
How Do I Update The createAsync() Signal?
I've been trying to use cache(), load(), and createAsync() because this pattern appears to be the preferred method for fetching data with SolidStart. Unfortunately, I can't figure out how to update the createAsync() signal. When using createStore() you get access to a getter and a setter:
const [ getNotes, setNotes ] = createStore([]);
const [ getNotes, setNotes ] = createStore([]);
But when using createAsync() I only get access to a getter.
const notes = createAsync(() => getNotes());
const notes = createAsync(() => getNotes());
How can I update the getter "notes" when using createAsync()?
33 replies
SSolidJS
Created by ChrisThornham on 5/10/2024 in #support
form action Breaking On Second Submit
To learn about actions, I built a simple notes app. The app displays a list of notes. When you click an edit button, the note text turns into a text input that can be edited. You can see what I'm describing in this code.
<Show
when={isEditing()}
fallback={<div>{props.noteText}</div>}
>
<form
action={updateNote}
method="post"
>
{/* New Note Input */}
<input
type="text"
name="note"
value={props.noteText}
placeholder={props.noteText}
/>
<input type="hidden" name="noteId" value={props.noteId} />
{/* Submit Button */}
<button>Save</button>
</form>
</Show>
<Show
when={isEditing()}
fallback={<div>{props.noteText}</div>}
>
<form
action={updateNote}
method="post"
>
{/* New Note Input */}
<input
type="text"
name="note"
value={props.noteText}
placeholder={props.noteText}
/>
<input type="hidden" name="noteId" value={props.noteId} />
{/* Submit Button */}
<button>Save</button>
</form>
</Show>
When you click save, the form calls the updateNote action.
const updateNote = action(async (formData: FormData) => {
// get note data
const newNote = formData.get("note");
const noteId = formData.get("noteId");

// update note in database...

setIsEditing(false);
});
const updateNote = action(async (formData: FormData) => {
// get note data
const newNote = formData.get("note");
const noteId = formData.get("noteId");

// update note in database...

setIsEditing(false);
});
The first time I perform an edit, the action works as expected. The edit is made and I stay on the same page. But if I try to make a second edit, the browser navigates to an action URL like this https://action/640465549 and the page shows a "This site can't be reached" message. I've noticed the same error occurs if you forget to include method="post" in your form. But in this case, I definitely have method="post" in my form. Does anyone know why this form is failing on the second submit? Thanks, Chris
4 replies
SSolidJS
Created by ChrisThornham on 5/9/2024 in #support
revalidate() Not Working As Expected
I'm fetching data from Supabase and using their Realtime feature so I can see live updates. To do that I'm using cache(), createAsync(), and revalidate() It looks like this: cache function:
const getNotes = cache(async () => {
"use server";
// get data
const { data } = await supabase.from("notes").select();
// return data
return data;
}, "notes");
const getNotes = cache(async () => {
"use server";
// get data
const { data } = await supabase.from("notes").select();
// return data
return data;
}, "notes");
createAsync function:
const notes = createAsync(() => getNotes());
const notes = createAsync(() => getNotes());
Here's where I'm confused. revalidate() works no matter what value I pass it. So all of these options will revalidate the notes Signal from createAsync. 1. revalidate() 2. revalidate("notes") 3. revalidate("some random string") I only expected option #2 to work. What am I missing? Thanks, Chris
10 replies
SSolidJS
Created by ChrisThornham on 4/25/2024 in #support
Help Me Stop Theme Flashing In SolidStart
I built a theme switcher using SolidStart. It works great, with one exception. On page reload, the theme flickers or flashes. It's happening because I'm using SSR mode. As a result, my ThemeProvider doesn't load the theme until the page loads. I believe I need to check the theme on the server so I can set the theme before my page loads using something like https://github.com/donavon/use-dark-mode/blob/develop/noflash.js.txt. Next.js has the next-themes package that does this for you. https://github.com/pacocoursey/next-themes I'm wondering how I can do this? Can anyone point me in the right direction? Or share some example code? I've pasted my ThemeProvider code in the next post:
20 replies
SSolidJS
Created by ChrisThornham on 4/15/2024 in #support
Why Would I Use An Action For Anything Other Than Form Submissions?
I’m struggling to understand why I would use an action for anything other than handling a form submission. Actions give you access to FormData, which simplifies working with forms. So, I can see a clear use case with forms. But why else would I use an action? Let me try to add some context to my confusion. The solid docs give the following example. I can use an action to do the following
import { action, useAction } from "@solidjs/router";

const echo = action(async (message: string) => {
// Imagine this is a call to fetch
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
console.log(message);
});

export default function MyComponent() {
const myEcho = useAction(echo);
myEcho("Hello from solid!");
}
import { action, useAction } from "@solidjs/router";

const echo = action(async (message: string) => {
// Imagine this is a call to fetch
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
console.log(message);
});

export default function MyComponent() {
const myEcho = useAction(echo);
myEcho("Hello from solid!");
}
BUT, I could also use a regular async function to achieve the same outcome in fewer lines of code.
async function echo(message: string) {
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
console.log(message);
}

export default function MyComponent() {
echo("Hello from solid!");
}
async function echo(message: string) {
await new Promise((resolve, reject) => setTimeout(resolve, 1000));
console.log(message);
}

export default function MyComponent() {
echo("Hello from solid!");
}
Additionally, the docs say: "after submitting data the server sends some data back as well. Usually an error message if something failed. Anything returned from your action function can be accessed using the reactive action.result property. " BUT, I can also use a try/catch block in a regular async function to return an error message. So, what's the point of actions outside of working with forms? Am I missing something? Or are actions just an alternative way to do what regular async functions can do? Thanks, Chris
22 replies
SSolidJS
Created by ChrisThornham on 4/10/2024 in #support
Help Me Understand SolidStart vs. Next.js Caching
I'm new to meta frameworks like SolidStart and I'm learning about Next.js to understand them better. Next.js automatically caches data for faster performance, but it seems SolidStart doesn't do this. Why is that? Does SolidStart's unique reactivity system mean it doesn't need caching like Next.js? If not, does using SolidStart mean sacrificing performance because it doesn't have automatic caching? Thanks, Chris
4 replies
SSolidJS
Created by ChrisThornham on 1/13/2024 in #support
How To Setup HTTPS on localhost
I've read through the Vite docs, and they suggest using the @vitejs/plugin-basic-ssl or vite-plugin-mkcert plugin to enable HTTPS on your localhost. I've tried the following two options and neither work. When I install mkcert and configure vite.config.ts as follows, the server won't start when I run npm run dev.
import { defineConfig } from "@solidjs/start/config";
import mkcert from 'vite-plugin-mkcert'

export default defineConfig({
start: { ssr: false },
plugins: [ mkcert() ]
});
import { defineConfig } from "@solidjs/start/config";
import mkcert from 'vite-plugin-mkcert'

export default defineConfig({
start: { ssr: false },
plugins: [ mkcert() ]
});
Alternatively, when I install basic-ssl and configure vite.config.tx as follows, the server will start, but I get a host of errors on http, and https won't load at all.
import { defineConfig } from "@solidjs/start/config";
import basicSsl from '@vitejs/plugin-basic-ssl';

export default defineConfig({
start: { ssr: false },
plugins: [
basicSsl()
]
});
import { defineConfig } from "@solidjs/start/config";
import basicSsl from '@vitejs/plugin-basic-ssl';

export default defineConfig({
start: { ssr: false },
plugins: [
basicSsl()
]
});
Here are the errors on https:
client.ts:77 WebSocket connection to 'ws://localhost:52194/_build/' failed:

client.ts:339 GET http://localhost:52194/_build/ net::ERR_EMPTY_RESPONSE
client.ts:77 WebSocket connection to 'ws://localhost:52194/_build/' failed:

client.ts:339 GET http://localhost:52194/_build/ net::ERR_EMPTY_RESPONSE
Here's the error on https:
crbug/1173575, non-JS module files deprecated.VM10:5
crbug/1173575, non-JS module files deprecated.VM10:5
Any suggestions would be appreciated. Thanks.
4 replies
SSolidJS
Created by ChrisThornham on 1/12/2024 in #support
Stripe Error: "ReferenceError: require is not defined"
I'm trying to add Stripe to a SolidStart project. In the Stripe docs, they ask you to initialize Stripe on the server with:
const stripe = require("stripe")('secret_key');
const stripe = require("stripe")('secret_key');
But require() doesn't work in SolidStart. You have to use import. After talking with Stripe, they said they didn't have an ES6 equivalent for initializing Stripe on the server. So... 1. How can I get around this problem? 2. Are there any good examples of how to get Stripe working in SolidStart?
4 replies
SSolidJS
Created by ChrisThornham on 1/12/2024 in #support
API Routes Not Found. Can You Help?
I've created a very simplified example to explain the errors I'm receiving when trying to create an API route. First, I created an API route in routes/api/create-payment-intent.ts. This route just logs the request body to keep things simple.
"use server";
import { type APIEvent } from "@solidjs/start/server/types";

export async function POST({ request }: APIEvent) {

console.log(request.body);

}
"use server";
import { type APIEvent } from "@solidjs/start/server/types";

export async function POST({ request }: APIEvent) {

console.log(request.body);

}
I've also created a page "StripePage" that uses fetch to make and HTTP POST request to the /api/create-payment-intent endpoint.
import { JSX, createEffect } from "solid-js";
import { Title } from "@solidjs/meta";

export default function StripePage(): JSX.Element {

createEffect(async () => {

fetch("/api/create-payment-intent", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ items: [{ id: "xl-tshirt" }] }),
});
});

return (
<>
<Title>Stripe Page</Title>
<div class="container">
<h1>Stripe Test Page</h1>
</div>
</>
);
}
import { JSX, createEffect } from "solid-js";
import { Title } from "@solidjs/meta";

export default function StripePage(): JSX.Element {

createEffect(async () => {

fetch("/api/create-payment-intent", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ items: [{ id: "xl-tshirt" }] }),
});
});

return (
<>
<Title>Stripe Page</Title>
<div class="container">
<h1>Stripe Test Page</h1>
</div>
</>
);
}
Here are the issues. 1. When I visit "StripePage" I get the following error:
POST http://localhost:3000/api/create-payment-intent 404 (Cannot find any path matching /api/create-payment-intent.).
This is odd because that route does exist. 2. Even though I'm getting a 404 error, I'm still getting a console.log() output. How is that possible if the route cannot be found? 3. If I was using Express, request.body would give me access to the items I passed in the body. But when I console.log(request.body) I get the following:
ReadableStream { locked: false, state: 'readable', supportsBYOB: false }
That output is not the JSON I passed in the body. So what am I doing wrong? Any help would be greatly appreciated.
6 replies
SSolidJS
Created by ChrisThornham on 1/2/2024 in #support
“use server”; Is Breaking Everything In My App
I’ve got one post going that touches on this subject of “use server”; breaking my app: A New Way to Chat with Friends & Communities I’ve been working on this for days at this point. If I use “use server”; on its own, it works. If I use client side code on its own, it works. But any time I try to pass data between the client and the server everything breaks. My last comment in the post above uses the example right out of the docs to show the errors. I get a long list of errors. $R reference errors, internal server errors, Uncaught type errors, etc. Basically, I can only work with the server OR the client, but not both at the same time. Is this expected behavior? Or are we supposed to be able to work with server-side and client-side code at the same time? For clarity sake, here’s a dead simple example. Here, clicking the “Run Function” button causes “Error from functionTwo” to be printed to the console. This is expected behavior.
export default function MyComponent() {

async function functionOne() {
try {
await functionTwo();
} catch (error: any) {
console.log(error.message);
}
}

async function functionTwo() {
throw new Error("Error from functionTwo");
}

return (
<button onClick={functionOne}>
Run Function
</button>
);
}
export default function MyComponent() {

async function functionOne() {
try {
await functionTwo();
} catch (error: any) {
console.log(error.message);
}
}

async function functionTwo() {
throw new Error("Error from functionTwo");
}

return (
<button onClick={functionOne}>
Run Function
</button>
);
}
But, when I add “use server”; to functionOne, it breaks.
export default function MyComponent() {

async function functionOne() {
"use server";
try {
await functionTwo();
} catch (error: any) {
console.log(error.message);
}
}

async function functionTwo() {
throw new Error("Error from functionTwo");
}

return (
<button onClick={functionOne}>
Run Function
</button>
);
}
export default function MyComponent() {

async function functionOne() {
"use server";
try {
await functionTwo();
} catch (error: any) {
console.log(error.message);
}
}

async function functionTwo() {
throw new Error("Error from functionTwo");
}

return (
<button onClick={functionOne}>
Run Function
</button>
);
}
Here’s the error:
chunk-6APUFJ5X.js:864 Uncaught TypeError: handler.call is not a function
at HTMLDocument.eventHandler
chunk-6APUFJ5X.js:864 Uncaught TypeError: handler.call is not a function
at HTMLDocument.eventHandler
38 replies
SSolidJS
Created by ChrisThornham on 1/1/2024 in #support
How Do I Update Client Signals When Using "use server";
I've set up a Supabase AuthService that tracks the error state with a signal.
export const [supabaseError, setSupabaseError] = createSignal("");
export const [supabaseError, setSupabaseError] = createSignal("");
If I get an error from Supabase, I set the error state in my AuthService file. Here's an example from my Logout function:
export async function supabaseLogout() {
try {
// try logging out
const { error } = await supabase.auth.signOut();
// throw an error if there is one
if (error) throw error;
} catch (error: any) {
// THIS WORKS
setSupabaseError(error.message);
}
}
export async function supabaseLogout() {
try {
// try logging out
const { error } = await supabase.auth.signOut();
// throw an error if there is one
if (error) throw error;
} catch (error: any) {
// THIS WORKS
setSupabaseError(error.message);
}
}
Any pages that use the AuthService can import the supabaseError signal, and display error messages when supabaseError().length > 0.
<Show when={supabaseError().length > 0}>
<div>
<p style={{ color: "#c62828" }}>{supabaseError()}</p>
</div>
</Show>
<Show when={supabaseError().length > 0}>
<div>
<p style={{ color: "#c62828" }}>{supabaseError()}</p>
</div>
</Show>
This works great when I do everything on the client. BUT, I'm running into trouble when I have to use "use server";. If I use setSupabaseError() from the server, the DOM does not update. For context, here's my action for deleting an account.
export const supabaseDeleteAccount = action(async (userId: string) => {
"use server";

// get the Auth Admin Client
const supabase = getAuthAdminClient();
if (!supabase) {
return;
}
try {
const { error } = await supabase.auth.admin.deleteUser(userId);
if (error) throw error;
} catch (error: any) {
// THIS DOESN'T WORK
setSupabaseError(error.message);
}
});
export const supabaseDeleteAccount = action(async (userId: string) => {
"use server";

// get the Auth Admin Client
const supabase = getAuthAdminClient();
if (!supabase) {
return;
}
try {
const { error } = await supabase.auth.admin.deleteUser(userId);
if (error) throw error;
} catch (error: any) {
// THIS DOESN'T WORK
setSupabaseError(error.message);
}
});
So, how can I update a client-side signal when using "use server";? The docs state the following about Global state and the server: "It is recommended that application state should always be provided via Context instead of relying on global." So, do I need to use context? Meta frameworks are new to me, so please excuse my ignorance 🙂 Thank you! Chris
35 replies
SSolidJS
Created by ChrisThornham on 12/28/2023 in #support
Using "use server"; But My Code Is Still Showing On Client. Why?
I'm trying to implement the new "use server"; comment to force parts of my code to run on the server. But it doesn't appear to be working. Here's an example. I have a AuthService.ts file that uses Supabase Auth. I'm trying to force the "delete user" code to run on the server. Here's the code:
async function supabaseDeleteAccount(session: AuthSession) {
// set loading true
setSupabaseAuthLoading(true);
try {
"use server";
const { error } = await supabaseServer.auth.admin.deleteUser(session.user.id);
if (error) throw error;
navigate("/", { replace: true });
} catch (error: any) {
// log the error and set the error state
console.log(error.message);
setSupabaseError(error.message);
} finally {
// set loading false
setSupabaseAuthLoading(false);
}
}
async function supabaseDeleteAccount(session: AuthSession) {
// set loading true
setSupabaseAuthLoading(true);
try {
"use server";
const { error } = await supabaseServer.auth.admin.deleteUser(session.user.id);
if (error) throw error;
navigate("/", { replace: true });
} catch (error: any) {
// log the error and set the error state
console.log(error.message);
setSupabaseError(error.message);
} finally {
// set loading false
setSupabaseAuthLoading(false);
}
}
My expectation, is that the code inside of the try block would run on the server. But if I run npm run dev and look at my AuthService.ts file in the Chrome Dev Tools Network tab, this is what I see...
async function supabaseDeleteAccount(session) {
setSupabaseAuthLoading(true);
try {
"use server";
const {error} = await supabaseServer.auth.admin.deleteUser(session.user.id);
if (error)
throw error;
navigate("/", {
replace: true
});
} catch (error) {
console.log(error.message);
console.log(error);
setSupabaseError(error.message);
} finally {
setSupabaseAuthLoading(false);
}
}
async function supabaseDeleteAccount(session) {
setSupabaseAuthLoading(true);
try {
"use server";
const {error} = await supabaseServer.auth.admin.deleteUser(session.user.id);
if (error)
throw error;
navigate("/", {
replace: true
});
} catch (error) {
console.log(error.message);
console.log(error);
setSupabaseError(error.message);
} finally {
setSupabaseAuthLoading(false);
}
}
Shouldn't the code below "use server"; in the try block NOT be visible in Chrome? Am I doing something wrong? Or is this a bug? Thanks, Chris
6 replies
SSolidJS
Created by ChrisThornham on 12/24/2023 in #support
NPM Start Error + Beginner Question
I'm new to SolidStart, and I've only been doing web dev with NPM for a few months. Typically, in all of the projects I've been building, I use npm run dev to view my project on a local server. I watched Ryan's "SolidStart: The Shape of Frameworks to Come" stream on YouTube, and I noticed he was using npm run build and npm run start. I ran npm run build and then npm run start in my project, and I got the following error after running npm run start.
> start
> node ./.output/server/index.mjs

file:///Users/project-path/.output/server/chunks/nitro/node-server.mjs:6501
throw new Error("Should be provided by compiler");
^

Error: Should be provided by compiler
at file:///Users/project-path/.output/server/chunks/nitro/node-server.mjs:6501:7
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
at async loadESM (node:internal/process/esm_loader:28:7)
at async handleMainPromise (node:internal/modules/run_main:113:12)

Node.js v21.4.0
> start
> node ./.output/server/index.mjs

file:///Users/project-path/.output/server/chunks/nitro/node-server.mjs:6501
throw new Error("Should be provided by compiler");
^

Error: Should be provided by compiler
at file:///Users/project-path/.output/server/chunks/nitro/node-server.mjs:6501:7
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
at async loadESM (node:internal/process/esm_loader:28:7)
at async handleMainPromise (node:internal/modules/run_main:113:12)

Node.js v21.4.0
So my first question is, does anyone know what's wrong with this? My second question is: Where can I learn more about the difference between: npm run dev npm run build npm run start I think you "build" a project and then deploy that project with the output, but I'm not sure. Long story short, I'd like to be more capable of handling these errors, but I don't know where to start.
Thanks, Chris
3 replies
SSolidJS
Created by ChrisThornham on 12/24/2023 in #support
How Do I Turn On SSR?
When I started my project, I enabled SSR. I thought that was all I had to do. But in Ryan's "The Shape of Frameworks to Come" stream on YouTube, he edits the vite.config.ts file from:
import { defineConfig } from "@solidjs/start/config";

export default defineConfig({});
import { defineConfig } from "@solidjs/start/config";

export default defineConfig({});
To:
import { defineConfig } from "@solidjs/start/config";

export default defineConfig({ start: { ssr: true }});
import { defineConfig } from "@solidjs/start/config";

export default defineConfig({ start: { ssr: true }});
Is that all you have to do? Or is there more to it? I don't see this step in the SolidStart docs. I assumed SolidStart controlled SSR. But if there is no information about turning on SSR in the SolidStart docs, then I must be wrong. So, is SSR a Vite thing? A SolidJS thing? Where can I read/learn more about working with and configuring SSR? Thanks, Chris
3 replies
SSolidJS
Created by ChrisThornham on 12/22/2023 in #support
"use server"; Help
I'm trying to understand how "use server"; works. Is it safe to assume that everything under "use server"; runs on the server (of course scope dependent). So, inside of the following function, only console.log(message); could run on the server.
const logHello = async (message: string) => {
"use server";
console.log(message);
};
const logHello = async (message: string) => {
"use server";
console.log(message);
};
However, when you call "use server"; at the top of a file, like in the server.ts file in the with-auth example, then all code runs on the server. Excerpt from the server.ts file from the with-auth example project.
"use server";
import { redirect } from "@solidjs/router";
import { useSession } from "@solidjs/start/server";
import { getRequestEvent } from "solid-js/web";
import { db } from "./db";

function validateUsername(username: unknown) {
if (typeof username !== "string" || username.length < 3) {
return `Usernames must be at least 3 characters long`;
}
}

function validatePassword(password: unknown) {
if (typeof password !== "string" || password.length < 6) {
return `Passwords must be at least 6 characters long`;
}
}
"use server";
import { redirect } from "@solidjs/router";
import { useSession } from "@solidjs/start/server";
import { getRequestEvent } from "solid-js/web";
import { db } from "./db";

function validateUsername(username: unknown) {
if (typeof username !== "string" || username.length < 3) {
return `Usernames must be at least 3 characters long`;
}
}

function validatePassword(password: unknown) {
if (typeof password !== "string" || password.length < 6) {
return `Passwords must be at least 6 characters long`;
}
}
I'm asking because the docs say... "To create a function that only runs on the server, pass a function as a parameter to server$." But I don't see any usage of server$ in the example projects. Thanks, Chris
6 replies