Uncontrolled State
No useState required — TreeKit manages expansion and checkbox state internally, seeded from defaults.
Most trees don't need their selection state read anywhere else in the app. For those, uncontrolled usage is less code and one less place to introduce a bug:
Show code
<TreeKit
data={data}
defaultExpandedIds={["engineering"]}
defaultCheckedIds={["react"]}
/>defaultExpandedIds and defaultCheckedIds only matter on first render — exactly like a native <input defaultValue>. Changing them on a later render has no effect, because from that point on the state lives inside TreeKit, not in your props.
Still want the callbacks?
onCheckedChange, onExpandedChange, onNodeClick, etc. alongside defaultCheckedIds. TreeKit will call them for visibility/analytics while continuing to manage the state itself; just don't also pass the controlled checkedIds prop, or you've made it controlled.Switching between the two
TreeKit determines controlled vs. uncontrolled per state slice, based on whether you pass checkedIds/expandedIds/selectedIds at all (not whether the value is truthy). Avoid switching a single tree instance between the two across renders — decide once, the same way you would for a native <input>, since flipping a prop from undefined to defined mid-lifecycle produces the same kind of inconsistent behavior React form inputs have.