From deef48f2603d7d74e4774ff71454d82d2d17703a Mon Sep 17 00:00:00 2001
From: Tyler Gnass <5575346+RBXTyler@users.noreply.github.com>
Date: Tue, 28 Oct 2025 19:17:12 -0400
Subject: [PATCH 1/2] Refactor DynamicList and ReactUtil for improved child
 reconciliation and performance

---
 src/Components/DynamicList.lua | 50 ++++++++++++++++++++++------------
 src/Utility/ReactUtil.lua      | 18 +++++++++---
 2 files changed, 47 insertions(+), 21 deletions(-)

diff --git a/src/Components/DynamicList.lua b/src/Components/DynamicList.lua
index 3877b14..49cc37e 100644
--- a/src/Components/DynamicList.lua
+++ b/src/Components/DynamicList.lua
@@ -5,37 +5,53 @@ local createElement = React.createElement
 local useState = React.useState
 local useEffect = React.useEffect
 local memo = React.memo
+local cloneElement = React.cloneElement
 
+-- DynamicList reconciles a dictionary of keyed children.
+-- Fixes: previous code wrapped ALL children with removal props each render causing churn & potential loops.
+-- Strategy: only wrap children flagged for removal; avoid mutating props; bail out when no change.
 local function DynamicList(props: { children: {} })
 	local children = props.children
 	local list, setList = useState({})
 
 	useEffect(function()
 		setList(function(prevState)
-			local state = table.clone(prevState)
+			local nextState = table.clone(prevState)
+			local changed = false
 
+			-- Add or update active children
 			for key, child in children do
-				state[key] = ReactUtil.updateReactChild(child)
-			end
-
-			for key, child in state do
-				if children[key] then
-					continue
+				local updated = ReactUtil.updateReactChild(child)
+				if nextState[key] ~= updated then
+					nextState[key] = updated
+					changed = true
 				end
+			end
 
-				child.props.remove = true
-				child.props.destroy = function()
-					setList(function(currentState)
-						local clonedState = table.clone(currentState)
-						clonedState[key] = nil
-						return clonedState
-					end)
+			-- Handle removals: mark existing entries not in children
+			for key, existing in nextState do
+				if children[key] == nil and existing ~= nil then
+					if not (existing.props and existing.props.remove) then
+						local wrapped = cloneElement(existing, {
+							remove = true,
+							destroy = function()
+								setList(function(currentState)
+									local cloned = table.clone(currentState)
+									cloned[key] = nil
+									return cloned
+								end)
+							end,
+						})
+						nextState[key] = ReactUtil.updateReactChild(wrapped)
+						changed = true
+					end
 				end
-
-				state[key] = ReactUtil.updateReactChild(child)
 			end
 
-			return state
+			if changed then
+				return nextState
+			end
+			return prevState
 		end)
 	end, { children })
 
diff --git a/src/Utility/ReactUtil.lua b/src/Utility/ReactUtil.lua
index 4425b08..7f24a70 100644
--- a/src/Utility/ReactUtil.lua
+++ b/src/Utility/ReactUtil.lua
@@ -1,9 +1,19 @@
-local TableUtil = require(script.Parent.TableUtil)
+-- ReactUtil provides lightweight helpers for dealing with React element descriptors.
+-- Deep copying a React element (as previously done) can erase Luau's refined type info
+-- and produce 'unknown' for consumers. For reconciliation we only need to ensure
+-- that a new table reference exists when we conceptually changed props.
 
-local function updateReactChild(child)
-	local cloned = TableUtil.deepCopy(child)
-	cloned.type = child.type
+local function updateReactChild(child: any)
+	-- If child is nil or not a table, just return it.
+	if type(child) ~= "table" then
+		return child
+	end
 
+	-- Shallow copy preserves element shape and keeps type field intact.
+	local cloned = {}
+	for k, v in child do
+		cloned[k] = v
+	end
 	return cloned
 end
 

From 6e17c163054692613b7bfa3d182c0b6309152b20 Mon Sep 17 00:00:00 2001
From: Tyler Gnass <5575346+RBXTyler@users.noreply.github.com>
Date: Tue, 28 Oct 2025 19:18:32 -0400
Subject: [PATCH 2/2] Remove TableUtil.lua as it is no longer needed

---
 src/Utility/TableUtil.lua | 17 -----------------
 1 file changed, 17 deletions(-)
 delete mode 100644 src/Utility/TableUtil.lua

diff --git a/src/Utility/TableUtil.lua b/src/Utility/TableUtil.lua
deleted file mode 100644
index cbb47a8..0000000
--- a/src/Utility/TableUtil.lua
+++ /dev/null
@@ -1,17 +0,0 @@
-type MixedArray = { [string | number]: any } | { any }
-
-local function deepCopy<T>(tbl: T): T
-	local new = table.clone(tbl :: any)
-
-	for key, value in tbl :: any do
-		if type(value) == "table" then
-			new[key] = deepCopy(value)
-		end
-	end
-
-	return (new :: any) :: T
-end
-
-return {
-	deepCopy = deepCopy,
-}
