Weird solid start behavior
I'm not sure I understand how solid router actions work. The following code is causing a hard full page refresh.
I'm also noticing none of my reactivity is work 😅
// src/hooks/createUserTheme.ts
import { createAsync, cache, action, json, reload } from "@solidjs/router";
import { createEffect, onCleanup } from "solid-js";
import { getCookie, setCookie } from "vinxi/http";
type Theme = "light" | "dark";
const DEFAULT: Theme = "dark",
THEME_KEY = "user-theme";
export const getThemeCookie = () => (getCookie(THEME_KEY) || "dark") as Theme;
export const getTheme = cache(async () => {
"use server";
return getThemeCookie();
}, THEME_KEY);
export const updateTheme = action(async (formData: FormData) => {
"use server";
const theme = formData.get(THEME_KEY)?.toString() || DEFAULT;
setCookie(THEME_KEY, theme);
return reload({ status: 200, revalidate: [THEME_KEY] });
}, THEME_KEY);
export const createUserTheme = () => {
const theme = createAsync(() => getTheme());
createEffect(() => {
const t = theme();
if (!t) return;
document.documentElement.classList.add(t);
onCleanup(() => {
document.documentElement.classList.remove(t);
});
});
return [theme, updateTheme] as const;
};
// src/components/ThemeToggle.tsx
import { createUserTheme, getTheme } from "~/hooks/createUserTheme";
export default function ThemeToggle() {
const [theme, updateTheme] = createUserTheme();
return (
<form action={updateTheme} method="post">
<input
type="hidden"
name={getTheme.key}
value={theme() === "light" ? "dark" : "light"}
/>
<button class="dark:bg-white bg-black text-white dark:text-black py-1.5 px-3 rounded-xl font-monument-regular ">
Toggle Theme
</button>
</form>
);
}
// src/hooks/createUserTheme.ts
import { createAsync, cache, action, json, reload } from "@solidjs/router";
import { createEffect, onCleanup } from "solid-js";
import { getCookie, setCookie } from "vinxi/http";
type Theme = "light" | "dark";
const DEFAULT: Theme = "dark",
THEME_KEY = "user-theme";
export const getThemeCookie = () => (getCookie(THEME_KEY) || "dark") as Theme;
export const getTheme = cache(async () => {
"use server";
return getThemeCookie();
}, THEME_KEY);
export const updateTheme = action(async (formData: FormData) => {
"use server";
const theme = formData.get(THEME_KEY)?.toString() || DEFAULT;
setCookie(THEME_KEY, theme);
return reload({ status: 200, revalidate: [THEME_KEY] });
}, THEME_KEY);
export const createUserTheme = () => {
const theme = createAsync(() => getTheme());
createEffect(() => {
const t = theme();
if (!t) return;
document.documentElement.classList.add(t);
onCleanup(() => {
document.documentElement.classList.remove(t);
});
});
return [theme, updateTheme] as const;
};
// src/components/ThemeToggle.tsx
import { createUserTheme, getTheme } from "~/hooks/createUserTheme";
export default function ThemeToggle() {
const [theme, updateTheme] = createUserTheme();
return (
<form action={updateTheme} method="post">
<input
type="hidden"
name={getTheme.key}
value={theme() === "light" ? "dark" : "light"}
/>
<button class="dark:bg-white bg-black text-white dark:text-black py-1.5 px-3 rounded-xl font-monument-regular ">
Toggle Theme
</button>
</form>
);
}
1 Reply
I'm not sure I understand how solid router actions work. The following code is causing a hard full page refresh.
I'm also noticing none of my reactivity is work 😅
So maybe that's the root of the issue. I'm not sure what's happening, the dev server is working just fine, but when I try to build I get the following error:
Yeah I've summed it up to some weird way that it's handling my actions, it's importing stuff it shouldn't from the server and I'm not too sure why.
Ahhh, okay, so you can't have
// src/hooks/createUserTheme.ts
import { createAsync, cache, action, json, reload } from "@solidjs/router";
import { createEffect, onCleanup } from "solid-js";
import { getCookie, setCookie } from "vinxi/http";
type Theme = "light" | "dark";
const DEFAULT: Theme = "dark",
THEME_KEY = "user-theme";
export const getThemeCookie = () => (getCookie(THEME_KEY) || "dark") as Theme;
export const getTheme = cache(async () => {
"use server";
return getThemeCookie();
}, THEME_KEY);
export const updateTheme = action(async (formData: FormData) => {
"use server";
const theme = formData.get(THEME_KEY)?.toString() || DEFAULT;
setCookie(THEME_KEY, theme);
return reload({ status: 200, revalidate: [THEME_KEY] });
}, THEME_KEY);
export const createUserTheme = () => {
const theme = createAsync(() => getTheme());
createEffect(() => {
const t = theme();
if (!t) return;
document.documentElement.classList.add(t);
onCleanup(() => {
document.documentElement.classList.remove(t);
});
});
return [theme, updateTheme] as const;
};
// src/components/ThemeToggle.tsx
import { createUserTheme, getTheme } from "~/hooks/createUserTheme";
export default function ThemeToggle() {
const [theme, updateTheme] = createUserTheme();
return (
<form action={updateTheme} method="post">
<input
type="hidden"
name={getTheme.key}
value={theme() === "light" ? "dark" : "light"}
/>
<button class="dark:bg-white bg-black text-white dark:text-black py-1.5 px-3 rounded-xl font-monument-regular ">
Toggle Theme
</button>
</form>
);
}
// src/hooks/createUserTheme.ts
import { createAsync, cache, action, json, reload } from "@solidjs/router";
import { createEffect, onCleanup } from "solid-js";
import { getCookie, setCookie } from "vinxi/http";
type Theme = "light" | "dark";
const DEFAULT: Theme = "dark",
THEME_KEY = "user-theme";
export const getThemeCookie = () => (getCookie(THEME_KEY) || "dark") as Theme;
export const getTheme = cache(async () => {
"use server";
return getThemeCookie();
}, THEME_KEY);
export const updateTheme = action(async (formData: FormData) => {
"use server";
const theme = formData.get(THEME_KEY)?.toString() || DEFAULT;
setCookie(THEME_KEY, theme);
return reload({ status: 200, revalidate: [THEME_KEY] });
}, THEME_KEY);
export const createUserTheme = () => {
const theme = createAsync(() => getTheme());
createEffect(() => {
const t = theme();
if (!t) return;
document.documentElement.classList.add(t);
onCleanup(() => {
document.documentElement.classList.remove(t);
});
});
return [theme, updateTheme] as const;
};
// src/components/ThemeToggle.tsx
import { createUserTheme, getTheme } from "~/hooks/createUserTheme";
export default function ThemeToggle() {
const [theme, updateTheme] = createUserTheme();
return (
<form action={updateTheme} method="post">
<input
type="hidden"
name={getTheme.key}
value={theme() === "light" ? "dark" : "light"}
/>
<button class="dark:bg-white bg-black text-white dark:text-black py-1.5 px-3 rounded-xl font-monument-regular ">
Toggle Theme
</button>
</form>
);
}
file: ./wedontknowyet/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vinxi/runtime/http.js:71:9
69: import { getContext as gContext } from "unctx";
70:
71: import { AsyncLocalStorage } from "node:async_hooks";
^
72:
73: /**
file: ./wedontknowyet/node_modules/.pnpm/[email protected]_@[email protected][email protected][email protected]/node_modules/vinxi/runtime/http.js:71:9
69: import { getContext as gContext } from "unctx";
70:
71: import { AsyncLocalStorage } from "node:async_hooks";
^
72:
73: /**
vinxi/http
imports in the same files that you have client facing code.
Isn't this something that could be fixed during build?
All I'm doing is getting cookies from a server function.