refactor: remove unnecessary features, update docs

This commit is contained in:
littensy 2025-11-02 18:55:41 -08:00
parent 7a88c784fa
commit 37f79ecc3f
20 changed files with 774 additions and 955 deletions

View file

@ -1,11 +1,11 @@
local suite = require("../../../../test/suite")
suite.describe("useAtom", function()
require("./useAtom.spec")
suite.describe("useSignalState", function()
require("./useSignalState.spec")
end)
suite.describe("useAtomBinding", function()
require("./useAtomBinding.spec")
suite.describe("useSignalBinding", function()
require("./useSignalBinding.spec")
end)
return {}

View file

@ -3,45 +3,43 @@ local ReactCharm = require("../")
local renderHook = require("./helpers/renderHook")
local suite = require("../../../../test/suite")
local atom = Charm.atom
local useAtomBinding = ReactCharm.useAtomBinding
local test = suite.test
test("tracks atom state", function()
local state = atom(0)
test("tracks signal state", function()
local getState, setState = Charm.signal(0)
local hook = renderHook(function()
return useAtomBinding(state)
return ReactCharm.useSignalBinding(getState)
end)
assert(hook.result:getValue() == 0, "should return 0")
state(1)
setState(1)
assert(hook.result:getValue() == 1, "should return 1")
end)
test("accepts a selector", function()
local state = atom(0)
local getState, setState = Charm.signal(0)
local hook = renderHook(function()
return useAtomBinding(function()
return 2 * state()
return ReactCharm.useSignalBinding(function()
return 2 * getState()
end)
end)
assert(hook.result:getValue() == 0, "should return 0")
state(1)
setState(1)
assert(hook.result:getValue() == 2, "should return 2")
end)
test("tracks dependencies", function()
local state = atom(0)
local getState, setState = Charm.signal(0)
local hook = renderHook(function()
return useAtomBinding(state, { state })
return ReactCharm.useSignalBinding(getState, { getState })
end)
assert(hook.result:getValue() == 0, "should return 0")
state(1)
setState(1)
assert(hook.result:getValue() == 1, "should return 1")
state = atom(0)
getState, setState = Charm.signal(0)
hook.rerender()
assert(hook.result:getValue() == 0, "should return 0")
state(1)
setState(1)
assert(hook.result:getValue() == 1, "should return 1")
end)

View file

@ -3,45 +3,43 @@ local ReactCharm = require("../")
local renderHook = require("./helpers/renderHook")
local suite = require("../../../../test/suite")
local atom = Charm.atom
local useAtom = ReactCharm.useAtom
local test = suite.test
test("tracks atom state", function()
local state = atom(0)
test("tracks signal state", function()
local getState, setState = Charm.signal(0)
local hook = renderHook(function()
return useAtom(state)
return ReactCharm.useSignalState(getState)
end)
assert(hook.result == 0, "should return 0")
state(1)
setState(1)
assert(hook.result == 1, "should return 1")
end)
test("accepts a selector", function()
local state = atom(0)
local getState, setState = Charm.signal(0)
local hook = renderHook(function()
return useAtom(function()
return 2 * state()
return ReactCharm.useSignalState(function()
return 2 * getState()
end)
end)
assert(hook.result == 0, "should return 0")
state(1)
setState(1)
assert(hook.result == 2, "should return 2")
end)
test("tracks dependencies", function()
local state = atom(0)
local getState, setState = Charm.signal(0)
local hook = renderHook(function()
return useAtom(state, { state })
return ReactCharm.useSignalState(getState, { getState })
end)
assert(hook.result == 0, "should return 0")
state(1)
setState(1)
assert(hook.result == 1, "should return 1")
state = atom(0)
getState, setState = Charm.signal(0)
hook.rerender()
assert(hook.result == 0, "should return 0")
state(1)
setState(1)
assert(hook.result == 1, "should return 1")
end)

View file

@ -1,29 +1,31 @@
import { Binding } from "@rbxts/react";
/**
* A hook that subscribes to changes in the given atom or selector. The
* component is re-rendered with the new state after an update.
* 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 `callback` when the dependencies change. Otherwise, the effect is
* current `getter` when the dependencies change. Otherwise, the effect is
* created only once, when the component is mounted.
*
* @param callback The atom or selector to watch.
* @param dependencies An array of values used to memoize the callback.
* @returns The current state.
* @param getter The signal or selector to watch.
* @param dependencies An array of values used to memoize the getter.
* @return The current state.
*/
export function useAtom<T>(callback: () => T, dependencies?: any[]): T;
export function useSignalState<T>(getter: () => T, dependencies?: any[]): T;
/**
* A hook that subscribes to changes in the given atom or selector. Returns
* a binding that updates when the state changes.
* 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 `callback` when the dependencies change. Otherwise, the effect is
* current `getter` when the dependencies change. Otherwise, the effect is
* created only once, when the component is mounted.
*
* @param callback The atom or selector to watch.
* @param dependencies An array of values used to memoize the callback.
* @returns A binding that stores the current state.
* @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.
*/
export function useAtomBinding<T>(callback: () => T, dependencies?: any[]): Binding<T>;
export function useSignalBinding<T>(getter: () => T, dependencies?: any[]): Binding<T>;
// Aliases
export { useSignalState as useAtom };

View file

@ -1,31 +1,30 @@
local Charm = require("./Charm")
local React = require("./React")
--- A hook that subscribes to changes in the given atom or selector. The
--- component is re-rendered with the new state after an update.
--- 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 atom or selector to watch.
--- @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 useAtom<T>(getter: () -> T, dependencies: { any }?): T
local state, setState = React.useState(getter)
local function useSignalState<T>(getter: () -> T, dependencies: { any }?): T
local value, setValue = React.useState(getter)
React.useLayoutEffect(function()
return Charm.effect(function()
-- Wrap in untracked to avoid tracking inner effect and atom calls
Charm.untracked(setState, getter())
Charm.untracked(setValue, getter())
end)
end, dependencies or {})
return state
return value
end
--- A hook that subscribes to changes in the given atom or selector. Returns
--- a binding that updates when the state changes.
--- 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
@ -34,9 +33,9 @@ end
--- @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 useAtomBinding<T>(getter: () -> T, dependencies: { any }?)
local initialState = React.useMemo(getter, {})
local binding, setBinding = React.useBinding(initialState)
local function useSignalBinding<T>(getter: () -> T, dependencies: { any }?)
local initialValue = React.useMemo(getter, {})
local binding, setBinding = React.useBinding(initialValue)
React.useLayoutEffect(function()
return Charm.effect(function()
@ -49,6 +48,7 @@ local function useAtomBinding<T>(getter: () -> T, dependencies: { any }?)
end
return {
useAtom = useAtom,
useAtomBinding = useAtomBinding,
useSignalState = useSignalState,
useSignalBinding = useSignalBinding,
useAtom = useSignalState,
}