S
SolidJS16mo ago
Revxrsal

question about stores and effects

o/ so i have a store that stores preferences (dark theme, etc.). i want to update the local storage whenever it changes. rn, i have an effect in the Root() component. i wonder if there's any way to hoist that logic outside
5 Replies
Revxrsal
RevxrsalOP16mo ago
i figured out this works:
export const [preferences, setPreferences] = createStore<Preferences>(
{
darkTheme: isSystemDarkMode()
}
)
createEffect(() => {
localStorage.setItem("preferences", JSON.stringify(preferences))
})
export const [preferences, setPreferences] = createStore<Preferences>(
{
darkTheme: isSystemDarkMode()
}
)
createEffect(() => {
localStorage.setItem("preferences", JSON.stringify(preferences))
})
but do effects have to be bound to a component?
ai6
ai616mo ago
Yes, you get warnings when using effects outside of components. But why do you need the effect outside? You can just make the store global and run the effect inside root. Or even better, create a Context
Revxrsal
RevxrsalOP16mo ago
Mainly for separation of concerns, I don't want the root to be responsible for updating preferences. But how would a context help here?
ai6
ai616mo ago
Here's how I use it:
const theme = createSignal("monokai");
export const ThemeContext = createContext(theme);

export default function Root() {

createEffect(async () => {
const cookie = () =>
parseCookie(
isServer ? event.request.headers.get("cookie") ?? "" : document.cookie
);
const t = cookie().theme ?? "monokai";
theme[1](t);
});

return (
<Html lang="en">
<Head>
<Title>SolidStart - With TailwindCSS</Title>
<Meta charset="utf-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1" />

<Link rel="manifest" href="manifest.json" />
</Head>
<ThemeContext.Provider value={theme}>
...
const theme = createSignal("monokai");
export const ThemeContext = createContext(theme);

export default function Root() {

createEffect(async () => {
const cookie = () =>
parseCookie(
isServer ? event.request.headers.get("cookie") ?? "" : document.cookie
);
const t = cookie().theme ?? "monokai";
theme[1](t);
});

return (
<Html lang="en">
<Head>
<Title>SolidStart - With TailwindCSS</Title>
<Meta charset="utf-8" />
<Meta name="viewport" content="width=device-width, initial-scale=1" />

<Link rel="manifest" href="manifest.json" />
</Head>
<ThemeContext.Provider value={theme}>
...
I think you can easily have these run in a separate file but you would still need to import it into root or another Higher Order Component.
belst
belst16mo ago
if you don't care about cleanup (eg the store exists for the whole lifetime of the application) u can just hoist it out and ignore the warning (created outside of createRoot) it is not bound to a component
Want results from more Discord servers?
Add your server