-
-
Save hipdev/e0c2c3cdd1ca5d76cfb2ccfa00089cb1 to your computer and use it in GitHub Desktop.
LFades state implementation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, useRef, useState } from "react"; | |
let atomCount = 0; | |
export function atom(initialValue) { | |
let value = initialValue; | |
let subs = []; | |
let id = `atom${atomCount++}`; | |
return Object.freeze({ | |
id, | |
get() { | |
return value; | |
}, | |
set(newValue) { | |
if (value === newValue) | |
return; | |
value = newValue; | |
subs.forEach((cb) => { | |
cb(value); | |
}); | |
}, | |
sub(cb) { | |
subs.push(cb); | |
return () => { | |
subs = subs.filter((sub) => sub !== cb); | |
}; | |
}, | |
}); | |
} | |
export function useAtom(atom) { | |
const [_count, rerender] = useState(0); | |
useSubscribe(atom, () => rerender((c) => c + 1)); | |
return [atom.get(), atom.set]; | |
} | |
export function useSubscribe(atom, cb, deps = []) { | |
useEffect(() => atom.sub(cb), [atom, ...deps]); | |
} | |
var HydrateState; | |
(function (HydrateState) { | |
HydrateState[HydrateState["Pending"] = 0] = "Pending"; | |
HydrateState[HydrateState["Done"] = 1] = "Done"; | |
HydrateState[HydrateState["Effect"] = 2] = "Effect"; | |
})(HydrateState || (HydrateState = {})); | |
export function useHydrate(cb, deps) { | |
const hydratedRef = useRef(HydrateState.Pending); | |
// Hydrate immediately for SSR and for the first render in the browser, this | |
// should avoid hydration mismatches. | |
if (hydratedRef.current === HydrateState.Pending) { | |
hydratedRef.current = HydrateState.Done; | |
cb(); | |
} | |
// This allows bundlers to remove the effect at build time. | |
if (typeof window !== "undefined") { | |
useEffect(() => { | |
// Prevent a double hydration and potential mismatch issues by running the | |
// callback only from the second render onwards. | |
if (hydratedRef.current === HydrateState.Done) { | |
hydratedRef.current = HydrateState.Effect; | |
} | |
else { | |
cb(); | |
} | |
}, deps); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment