From 02be296b3d8a6c8a410d58a542a0335d3fac4ffa Mon Sep 17 00:00:00 2001 From: littensy <56808540+littensy@users.noreply.github.com> Date: Sat, 20 Jun 2026 20:45:50 -0700 Subject: [PATCH] docs: add warning for deep-charm and note for `observe()` --- README.md | 19 +++++++++ packages/deep-charm/test/reactive.test.luau | 43 +++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/README.md b/README.md index 07b361d..35895ac 100644 --- a/README.md +++ b/README.md @@ -885,6 +885,9 @@ You can opt-in to deep reactivity with the Deep Charm library: ### Installation +> [!WARNING] +> Deep Charm is an experimental library that is not fully documented, and the API is subject to breaking changes. + ```sh npm install @rbxts/deep-charm yarn add @rbxts/deep-charm @@ -940,6 +943,22 @@ local proxy = reactive(raw) print(toRaw(proxy) == raw) -- true ``` +Calling `toRaw()` on a proxy also subscribes to its changes. This allows you to use proxies with `observe()` and other Charm APIs that accept a getter function: + +```luau +local proxy, updateProxy = reactive({}) + +observe(function() + return toRaw(proxy) +end, function(value, key) + print(`Value {value} added at key {key}`) +end) + +updateProxy(function(state) + table.insert(state, "foo") +end) -- Value foo added at key 1 +``` + --- ### `isReactive(value)` diff --git a/packages/deep-charm/test/reactive.test.luau b/packages/deep-charm/test/reactive.test.luau index b663147..41654b1 100644 --- a/packages/deep-charm/test/reactive.test.luau +++ b/packages/deep-charm/test/reactive.test.luau @@ -2,7 +2,10 @@ local Charm = require("../Charm") local DeepCharm = require("../src") local test = require("../../../tests/test") +local batch = Charm.batch +local computed = Charm.computed local effect = Charm.effect +local observe = Charm.observe local reactive = DeepCharm.reactive local toRaw = DeepCharm.toRaw @@ -186,4 +189,44 @@ test("should unwrap nested proxy", function() assert(runs == 3, `bad runs: {runs}`) end) +test("should observe items", function() + local items, updateItems = reactive({ 0, 0, 0 }) + local updates = {} + local cleanups = {} + + observe(function() + return toRaw(items) + end, function(_, key: number) + local get = computed(function() + return items[key] + end) + + effect(function() + table.insert(updates, get()) + end) + + return function() + table.insert(cleanups, key) + end + end) + + assert(table.concat(updates) == "000", `bad mount: {table.concat(updates)}`) + + table.clear(updates) + updateItems(function(state) + state[1] = 1 + state[2] = 2 + state[3] = 3 + end) + assert(table.concat(updates) == "123", `bad update: {table.concat(updates)}`) + + table.clear(updates) + batch(function() + items[3] = nil + items[4] = 4 + end) + assert(table.concat(updates) == "4", `should add 4: {table.concat(updates)}`) + assert(table.concat(cleanups) == "3", `bad cleanup: {table.concat(cleanups)}`) +end) + return {}