S
SolidJS•2mo ago
Kooki Kodes

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.
// 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>
);
}
I'm also noticing none of my reactivity is work 😅
1 Reply
Kooki Kodes
Kooki KodesOP•2mo ago
I'm not sure I understand how solid router actions work. The following code is causing a hard full page refresh.
// 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>
);
}
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:
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: /**
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 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.
Want results from more Discord servers?
Add your server