local Charm = require("./Charm") local React = require("./React") --[[ Returns a React state that updates when the getter function updates. Re-renders the component when the value changes. If the `dependencies` array is provided, a new effect is created for the current `getter` when the dependencies change. Otherwise, the effect is created only once, when the component is mounted. @param getter The signal or selector to watch. @param dependencies An array of values used to memoize the getter. @return The current state. ]] local function useSignalState(getter: () -> T, dependencies: {}?): T local value, setValue = React.useState(getter) React.useLayoutEffect(function(): () -> () return Charm.listen(getter, setValue :: (T, T?) -> ()) end, dependencies :: { any } or {}) return value end --[[ Returns a React binding that updates when the getter function updates. If the `dependencies` array is provided, a new effect is created for the current `getter` when the dependencies change. Otherwise, the effect is created only once, when the component is mounted. @param getter The atom or selector to watch. @param dependencies An array of values used to memoize the getter. @return A binding that stores the current state. ]] local function useSignalBinding(getter: () -> T, dependencies: {}?) local initialValue = React.useMemo(getter, {}) local binding, setBinding = React.useBinding(initialValue) React.useLayoutEffect(function(): () -> () return Charm.listen(getter, setBinding :: (T, T?) -> ()) end, dependencies :: { any } or {}) return binding end return table.freeze({ useSignalState = useSignalState, useSignalBinding = useSignalBinding, useAtom = useSignalState, })