Removing useEffect with Effect Atom
Getting a bit into using Effect Atom now and loving it so far.
Is there a way to get rid of the useEffect here and do it as a Atom sideeffect or similar?
Is there a way to get rid of the useEffect here and do it as a Atom sideeffect or similar?
import { BrowserKeyValueStore } from "@effect/platform-browser"
import { Atom, useAtomSet, useAtomValue } from "@effect-atom/atom-react"
import { Schema } from "effect"
import { useEffect } from "react"
export type Theme = "dark" | "light" | "system"
type ThemeProviderProps = {
children: React.ReactNode
defaultTheme?: Theme
storageKey?: string
}
const ThemeSchema = Schema.Literal("dark", "light", "system")
const localStorageRuntime = Atom.runtime(BrowserKeyValueStore.layerLocalStorage)
export const themeAtom = Atom.kvs({
runtime: localStorageRuntime,
key: "hazel-ui-theme",
schema: Schema.NullOr(ThemeSchema),
defaultValue: () => "system" as const,
})
export const resolvedThemeAtom = Atom.make((get) => {
const theme = get(themeAtom)
if (theme === "system") {
if (typeof window !== "undefined") {
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
}
return "light"
}
return theme || "system"
})
export function ThemeProvider({ children }: ThemeProviderProps) {
const resolvedTheme = useAtomValue(resolvedThemeAtom)
useEffect(() => {
const root = window.document.documentElement
root.classList.remove("light", "dark")
root.classList.add(resolvedTheme)
}, [resolvedTheme])
return <>{children}</>
}
export const useTheme = () => {
const theme = useAtomValue(themeAtom)
const setTheme = useAtomSet(themeAtom)
return {
theme: theme || "system",
setTheme,
}
}import { BrowserKeyValueStore } from "@effect/platform-browser"
import { Atom, useAtomSet, useAtomValue } from "@effect-atom/atom-react"
import { Schema } from "effect"
import { useEffect } from "react"
export type Theme = "dark" | "light" | "system"
type ThemeProviderProps = {
children: React.ReactNode
defaultTheme?: Theme
storageKey?: string
}
const ThemeSchema = Schema.Literal("dark", "light", "system")
const localStorageRuntime = Atom.runtime(BrowserKeyValueStore.layerLocalStorage)
export const themeAtom = Atom.kvs({
runtime: localStorageRuntime,
key: "hazel-ui-theme",
schema: Schema.NullOr(ThemeSchema),
defaultValue: () => "system" as const,
})
export const resolvedThemeAtom = Atom.make((get) => {
const theme = get(themeAtom)
if (theme === "system") {
if (typeof window !== "undefined") {
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"
}
return "light"
}
return theme || "system"
})
export function ThemeProvider({ children }: ThemeProviderProps) {
const resolvedTheme = useAtomValue(resolvedThemeAtom)
useEffect(() => {
const root = window.document.documentElement
root.classList.remove("light", "dark")
root.classList.add(resolvedTheme)
}, [resolvedTheme])
return <>{children}</>
}
export const useTheme = () => {
const theme = useAtomValue(themeAtom)
const setTheme = useAtomSet(themeAtom)
return {
theme: theme || "system",
setTheme,
}
}