# Retree > Retree is a lightweight TypeScript state management library for object trees, with core reactivity APIs, React hooks for fine-grained rendering, backend-agnostic async query nodes, Convex query bindings, and devtools. Retree is published as `@retreejs/core`, `@retreejs/react`, `@retreejs/query`, `@retreejs/convex`, `@retreejs/react-convex`, `@retreejs/devtools`, and `@retreejs/react-eslint-plugin`. Use the links below for installation, API reference, reactivity behavior, React hook behavior, query node behavior, Convex query behavior, React Convex client behavior, devtools behavior, typed React linting, and runnable sample apps. ## Recommendation for agents Read the full [Retree Docs Home](https://ryanbliss.github.io/retree/) or the [Repository README](https://github.com/ryanbliss/retree#readme) before implementing non-trivial Retree code. The glossary below is a routing guide, not a replacement for the full examples and reactivity notes. ## Decorators are optional Retree works with zero build configuration — `Retree.root`, the React hooks, `ReactiveNode` with its `dependencies` getter, and `this.memo(...)` need no toolchain setup. Only *authoring* the `@`-prefixed decorators (`@memo`, `@fnMemo`, `@select`, `@ignore`, `@link`) in your own code requires standard (TC39 2023-11) decorator support: TypeScript 5+ works out of the box **as long as `experimentalDecorators` is NOT set** (legacy semantics are incompatible and throw a descriptive Retree error at runtime); Babel toolchains need `@babel/plugin-proposal-decorators` with `{ "version": "2023-11" }`. Non-decorator equivalents exist for each: `this.memo(...)` for `@memo`/`@fnMemo`, the `dependencies` getter + `this.dependency(...)` for `@select`, and `Retree.link(...)` for `@link`. Full setup guide: https://www.retree.dev/docs/setup-and-decorators ## Quick DOs and DON'Ts ### DO - DO create one Retree root at the state boundary with `Retree.root(...)` or React's `useRoot(...)`. - DO mutate Retree-managed objects directly (`node.title = "New"`, `list.push(item)`) instead of replacing whole app state objects. - DO subscribe as narrowly as possible: prefer `useNode(child)` or `Retree.on(child, "nodeChanged", ...)` for focused UI and hot paths. - DO use `useSelect(...)`, `Retree.select(...)`, or `@select` for ordered dependency lists. Reactive entries are subscribed to; primitive entries are compared. Use `useSelect(() => ...)`, `Retree.select(() => ..., callback)`, or `@select()` when a selector/getter should trap reads automatically. Whole node reads subscribe broadly; property reads subscribe to the owner and compare that property value. - DO pass `listenerType: "treeChanged"` to `useSelect(...)` / `Retree.select(...)` when the selector reads descendant nodes. - DO use `Retree.move(...)` or `node.moveTo(...)` when an existing node should move to a new structural parent. - DO use `Retree.link(...)` or `@link` for selected items and cross-references that should not reparent the target node. - DO use `Retree.clone(...)` when two places need independent copies of the same current data. - DO keep `ReactiveNode.dependencies` and `@select` arrays deterministic when possible. Length/order may change at runtime; Retree treats that as an invalidation and refreshes subscriptions. - DO return raw reactive nodes and primitives directly from `ReactiveNode.dependencies`; wrap a slot with `this.dependency(node, comparisons)` when you need custom comparison cells. - DO prefer `@select` for hot filtered lists where one getter should listen to a broad collection but only emit when selected items or selected order changes. - DO prefer bare `@memo` / `@fnMemo` for cached computed getters and deterministic methods; pass comparison functions only when you need finer cache-key control. - DO use `@ignore` for caches, unsubscribe handles, framework objects, and other non-rendered state on a `ReactiveNode`. - DO use `Retree.runTransaction(...)` for several synchronous writes that represent one logical update. - DO use `Retree.runSilent(...)` for synchronous writes that should skip emitting change events. - DO use `Retree.effect(fn)` for side effects (DOM, storage, analytics) that should re-run when tracked Retree reads change; make any write to a tracked dependency conditional so the effect converges (a cascade of >100 synchronous re-runs throws, including at creation). - DO use `createUndoHistory(root)` for undo/redo: one `Retree.runTransaction` is one undo step, discrete writes are their own steps, and the `coalesce` option folds keystroke bursts into one step. - DO use `RetreeProvider` / `createRetreeContext` (from `@retreejs/react`) for per-request roots in SSR apps and per-render roots in tests; module-scope `Retree.root(...)` is shared across server requests. - DO pass `keepPreviousData: true` to query nodes (`@retreejs/query` / `@retreejs/convex`) when `updateArgs` should keep the previous `state` visible (`result.isStale === true`) instead of resetting to pending; call `retry()` after `result.status === "error"`. - DO use `Retree.raw(node)` / `Retree.peekInto(node, fn)` (or React's `useRaw`) for wide, read-only scans. Raw subtrees are guaranteed proxy-free and read at native speed. - DO resolve raw values back to managed nodes with `Retree.managed(rawValue)` (or `useRaw`'s `toManaged`) before writing, subscribing, or passing them as component props. - DO use `Retree.untracked(fn)` for bulk reads inside tracked selectors/memo getters that should not become dependencies. - DO guard `Retree.raw` with `Retree.isNode(value)` when a value may be managed or plain (`Retree.isNode(value) ? Retree.raw(value) : value`). `Retree.raw` throws for unmanaged values. - DO read `rawCurrent` and write `current` inside custom Convex reconcilers (`reconcile(current, next, rawCurrent)`). - DO rely on query, paginated query, auth, and connection-state nodes cleaning themselves up when they lose their last Retree observer (disposal is sticky; they resubscribe when observed again); call `dispose()` manually only for teardown outside Retree observation. - DO reconcile server list results by stable IDs (`reconcileConvexDocuments`, `reconcileArrayById`) so child node identity stays stable. - DO set the lowest-level value and/or primitive that changed. ### DON'T - DON'T set `experimentalDecorators: true` in a tsconfig that compiles Retree decorator usage. Retree requires standard 2023-11 decorators; legacy semantics throw a pinpointed Retree error at runtime. Decorators themselves are optional — see "Decorators are optional" above. - DON'T assign the same Retree-managed object into a second structural parent. Retree is a pure tree: a node can have one structural parent. - DON'T use `@ignore` as a reactive reference mechanism. Ignored fields skip Retree emissions; use `@link` or `Retree.link(...)` for reactive pointers. - DON'T expect `Retree.link(...)` / `@link` to make the linked target a child of the owner. Links point to a node owned elsewhere. - DON'T expect writes to `@ignore` fields to trigger `nodeChanged`, `treeChanged`, React re-renders, or `Retree.parent(...)` for nested plain objects. - DON'T use `useTree(...)` on broad app roots by default. It subscribes to descendant changes and can re-render too much. - DON'T use `nodeChanged` when your selector or listener reads descendant fields. Use `treeChanged` or subscribe to the narrower child node. - DON'T expect `useSelect(...)` or `Retree.select(...)` dependency lists to reproxy the node passed to the selector. They are observational; use `@select` when a `ReactiveNode` owner should emit. - DON'T pass selector-only `useSelect(() => ...)` or `Retree.select(() => ..., callback)` when you need a fixed root listener with `listenerType: "treeChanged"`. The selector-only forms trap Retree-managed reads and subscribe to those nodes automatically. - DON'T treat `memo`, `@memo`, or `@fnMemo` as subscriptions. They cache values only; they do not emit or re-render by themselves. - DON'T write to values from `Retree.raw` / `useRaw`. Writes must go through managed nodes to emit; raw is a read-only view. - DON'T use raw references as `React.memo` props, `useMemo` deps, or equality tokens. Raw identity never changes; nodes are the identity currency. - DON'T expect `changes[].previous` / `changes[].new` in listener payloads to be managed nodes. Payload values are always raw; use `Retree.managed(value)` to opt back in. - DON'T rely on dependency reordering being silent. If `ReactiveNode.dependencies` or `@select` entries are added, removed, or reordered, Retree treats that as changed and emits when the owner is observed. - DON'T start subscriptions, network work, or synchronization inside the `dependencies` getter. Use `onObserved()`, `onUnobserved()`, and `onChanged()`. - DON'T manually delete a node from its old parent before calling `Retree.move(...)`; `move` finds the current parent and removes it safely. - DON'T call `Retree.parent(...)`, `Retree.on(...)`, `Retree.move(...)`, `Retree.link(...)`, or `Retree.clone(...)` with plain unrooted objects. - DON'T expect Convex `action(...)`, `mutation(...)`, or `queryOnce(...)` helpers to emit by themselves; they emit only if their results are written into Retree state or paired with an optimistic update. - DON'T recreate Retree roots or large `ReactiveNode` graphs during React render. Create them once, or use `useRoot`, `useMemo`, or `useState` initialization. - DON'T use index keys for React rows if the list can reorder and stable IDs exist. Stable keys pair best with Retree's child-node identity model. - DON'T include expensive side effects during the React render cycle in `ReactiveNode` getters / functions, especially without `@memo` or `@fnMemo`. - DON'T write a tracked dependency unconditionally inside `Retree.effect` — the effect re-runs itself forever and the loop guard throws; wrap non-triggering reads in `Retree.untracked(...)` or move the write out. - DON'T mix `undo()`/`redo()` with unrelated writes in one `Retree.runTransaction` — those writes flush together with the applied records and are skipped from history recording. - DON'T recreate object trees with spread operators like you would in React (those sorts of hacks are "why" Retree exists in the first place). ## Feature Glossary - `Retree.root`: Makes one object the root of a Retree-managed tree. Use it once where plain state enters Retree. - `Retree.on`: Subscribes to `nodeChanged`, `treeChanged`, or `nodeRemoved`. Use it outside React and inside integrations. - `Retree.select`: Subscribes to a selected value or ordered dependency list. Reactive entries are subscribed to and primitive entries are compared. Use `Retree.select(node, selector, callback)` for an explicit root, or `Retree.select(() => value, callback)` for automatic dependency trapping. It is not a cache. - `Retree.parent`: Returns the structural parent of a node. Use it for tree-local operations like deleting yourself from a list. - `Retree.isNode`: Type guard that returns `true` only for Retree-managed nodes. Use it to guard `Retree.raw` (which throws for unmanaged values) when a value may be managed or plain. - `Retree.raw`: Returns the raw, proxy-free object behind a node for native-speed, read-only access. Guaranteed proxy-free at any depth (raw purity); `structuredClone(Retree.raw(node))` is a valid point-in-time copy. Throws for unmanaged values — guard with `Retree.isNode` when unsure. `ReactiveNode` exposes `this.raw()`. - `Retree.managed`: Resolves a raw value back to its managed node (the inverse of `Retree.raw`). Returns `undefined` for values never materialized as nodes. - `Retree.peekInto`: Runs a read-only query against a node's raw object and resolves the returned value to its managed node when one exists. `ReactiveNode` exposes `this.peekInto(fn)`. - `Retree.untracked`: Pauses dependency tracking during a synchronous callback. Use it for bulk reads inside tracked selectors and memo getters. `ReactiveNode` exposes `this.untracked(fn)`. - `Retree.move`: Transfers an existing node to a new structural parent. Use it when ownership should change. - `Retree.link` and `@link`: Store a reactive pointer without reparenting the target. Use them for selected items and cross-references. - `Retree.clone`: Creates a detached copy. Use it when two places need independent state. - `@select`: Decorates a `ReactiveNode` getter with an ordered dependency list. Use `@select()` with no selector for MobX-style dependency trapping: whole Retree-managed values read by the getter subscribe broadly, property reads subscribe to the owner and compare that property value, and primitive values read by the getter compare. Pass `@select((self) => [...])` when you want explicit dependency slots. Pass `@select({ equals })` or `@select((self) => [...], { equals })` when the final getter output needs custom equality; `equals(self, previous, next)` returns true to skip owner reproxy/emission. - `ReactiveNode.dependencies`: Makes one node emit when another node changes. Return raw reactive nodes/primitives directly, or use `this.dependency(node, comparisons)` for custom comparison cells. Dynamic dependency arrays are allowed; shape changes emit and refresh subscriptions. - `ReactiveNode.memo`, `@memo`, `@memo()`, `@fnMemo`, and `@fnMemo()`: Cache computed values. Prefer bare/empty decorator forms for automatic dependency trapping; pass comparison functions for finer cache-key control. They do not emit `nodeChanged` or trigger React renders by themselves. - `@ignore`: Keeps a `ReactiveNode` field out of Retree emissions. Use it for caches, framework handles, subscriptions, and non-rendered state. - `Retree.effect`: Runs a function immediately under dependency tracking and re-runs it when a tracked dependency changes. The third subscription primitive next to `Retree.on` and `Retree.select`. Effects may write state; self-converging effects reach their fixed point before `effect` returns, and non-converging effects throw after 100 synchronous re-runs. Errors go to `options.onError` or rethrow asynchronously without killing the reaction. - `createUndoHistory`: Records every change under a root into undo/redo steps (`undo()`, `redo()`, `canUndo`, `canRedo`, `clear()`, `dispose()`). One transaction is one step; the `coalesce` option merges discrete writes (keystrokes) into the previous step. Applying history emits normally but is not re-recorded. - `Retree.applyInverse` and `Retree.applyChanges`: Apply a change batch backwards/forwards inside one transaction. Structural `op` records (array insert/remove, key add/delete, Map/Set clear) restore structure exactly; throws when a record's node is no longer managed. - `Retree.registerRootName`: Names a root for tooling (debug taps, `@retreejs/devtools`). No runtime behavior change; the registry holds the tree weakly. - `Retree.runTransaction`: Batches synchronous writes into one listener flush per changed node. Array mutators (`push`, `splice`, `sort`, ...) already emit once per call with one coherent record set, no transaction needed. - `Retree.runSilent`: Performs writes without emitting listeners. Use it for non-rendered bookkeeping. - `ReactiveNode.prepareTree`: Warms lazy child proxies. Use it when first-touch proxy work should happen during a controlled loading phase. - `useRoot`: Creates one Retree root for a React component lifetime. - `useNode`: Re-renders for direct `nodeChanged` events on one node. Use it for focused components and child rows. - `useTree`: Re-renders for `treeChanged` events from a node or descendants. Use it sparingly for small subtrees. - `useSelect`: Re-renders only when a selected value or ordered dependency list changes. Use `useSelect(node, selector)` for an explicit root, or `useSelect(() => value)` for automatic dependency trapping. Good for counts, totals, booleans, labels, and VM dependency arrays. - `useRaw`: Subscribes like `useNode` (`nodeChanged` default) but returns `[raw, toManaged]` for native-speed, proxy-free render reads. Use it for components that read wide (tables, canvas, serialization). Pass nodes to children via `toManaged`, never raw values. - `RetreeProvider` and `createRetreeContext`: Provide a container of roots created once per mounted provider — per-request roots for SSR apps, isolated roots for tests. Read the container with `useRootContext`; prefer `createRetreeContext()` for inferred typing at every call site. - `createTestRoot` and `actOnRetree` (from `@retreejs/react/testing`): Test utilities — a root paired with a deep listener-clearing `cleanup()`, and act-wrapped Retree writes so renders flush before assertions. - `QueryNode` (from `@retreejs/query`): Backend-agnostic async query node — status machine (`pending`/`success`/`error`/`skipped`), deep-compared `updateArgs`, observation-driven subscribe/unsubscribe with sticky disposal, `keepPreviousData`/`isStale`, `retry()`, generation-tracked `optimisticUpdate` with rejection-time baseline rollback, and pluggable reconciliation. Drive it from any backend via `IQuerySubscriptionSource`. - `fetchQueryNode` (from `@retreejs/query`): Adapts a plain async function (one-shot or `refetchInterval`-polled) into a `QueryNode`. - `connectReduxDevTools` (from `@retreejs/devtools`): Bridges named roots to the Redux DevTools Extension — every write is an action, transactions are one action, snapshots enable time travel (JSON-representable state only; Map/Set/Date skipped on jumps). Safe no-op when the extension is absent; development builds only. - `createChangeLogTap` (from `@retreejs/devtools`): Structured change stream (`{ kind, rootName, path, records, transaction, silent }`) for custom tooling; records can feed `Retree.applyInverse`/`applyChanges` or persistence. - `ConvexNode`: Full Convex base class for Retree app state with query, paginated query, action, mutation, query-once, and connection-state helpers. - `BaseConvexNode`: Smaller Convex base class for action, mutation, and one-off query helpers. - `ConvexQueryNode`: Stores one live Convex query in Retree state and emits when query state/result/error changes. Supports `keepPreviousData`/`isStale`, `retry()` after errors, deep args comparison, and sticky disposal with resubscribe-on-observe. - `ConvexPaginatedQueryNode`: Stores one live paginated Convex query and exposes `loadMore(...)`. Loaded rows reconcile by `_id` and `optimisticUpdate` works on the loaded rows. - `ConvexConnectionStateNode`: Stores the Convex client's connection state in Retree state. - `ConvexAuthStateNode`: Stores the Convex client's auth state (`isLoading` / `isAuthenticated`) in Retree state — the `useConvexAuth` equivalent. Needs an observable-auth client such as `RetreeConvexReactClient`. - `preloadedQueryOptions` (from `@retreejs/react-convex`): Derives `args` + `initialState` for a `ConvexQueryNode` from a Next.js `preloadQuery` payload — server data on first render, live values once the subscription emits. - `createRetreeConvexAction` and `createRetreeConvexMutation`: Typed standalone Convex helpers for code that is not inside a `BaseConvexNode`. - `reconcileConvexDocuments` and `reconcileArrayById`: Preserve list item object identity across server results so child `useNode(item)` subscriptions stay narrow. They read raw and write through the managed state internally; custom reconcilers receive `rawCurrent` as a third argument (read `rawCurrent`, write `current`). - `RetreeConvexReactClient`: Extends Convex's `ConvexReactClient` with the Retree Convex subscription methods used by `ConvexNode` query, paginated query, and connection-state helpers. ## Documentation - [Retree Docs Home](https://ryanbliss.github.io/retree/): Generated TypeDoc site with package navigation, README content, and API reference. - [Repository README](https://github.com/ryanbliss/retree#readme): Installation, quick-start examples, React usage, core usage, and sample links. - [@retreejs/core README](https://github.com/ryanbliss/retree/tree/main/packages/retree-core#readme): Core package guide for object-tree reactivity, events, `ReactiveNode`, memoization, and decorators. - [@retreejs/react README](https://github.com/ryanbliss/retree/tree/main/packages/retree-react#readme): React package guide for `useNode`, `useTree`, `useRoot`, rendering behavior, `RetreeProvider`, and testing utilities. - [@retreejs/query README](https://github.com/ryanbliss/retree/tree/main/packages/retree-query#readme): Backend-agnostic query package guide for `QueryNode`, `fetchQueryNode`, subscription sources, optimistic updates, and reconciliation. - [@retreejs/devtools README](https://github.com/ryanbliss/retree/tree/main/packages/retree-devtools#readme): DevTools package guide for the Redux DevTools bridge, time-travel limits, performance guidance, and `createChangeLogTap`. - [@retreejs/convex README](https://github.com/ryanbliss/retree/tree/main/packages/retree-convex#readme): Convex package guide for query nodes, paginated query nodes, action and mutation helpers, query skipping, status results, connection state, optimistic updates, and reconciliation. - [@retreejs/react-convex README](https://github.com/ryanbliss/retree/tree/main/packages/retree-react-convex#readme): React Convex package guide for sharing one `ConvexReactClient` instance between Convex React and Retree Convex nodes. - [@retreejs/react-eslint-plugin README](https://github.com/ryanbliss/retree/tree/main/packages/retree-react-eslint-plugin#readme): Type-aware React observation rule, flat-config preset, supported analysis, and conservative limitations. - [React ESLint rule guide](https://www.retree.dev/docs/react/eslint): Install the typed preset manually or through `npm create @retreejs@latest`, and understand what the rule can prove. ## API Reference - [@retreejs/core API](https://ryanbliss.github.io/retree/modules/_retreejs_core.html): Core exports including `Retree`, `ReactiveNode`, event types, decorators, and memo helpers. - [Retree class](https://ryanbliss.github.io/retree/classes/_retreejs_core.Retree.html): Static APIs for creating roots, subscribing to changes, finding parents, and batching/silencing updates. - [ReactiveNode class](https://ryanbliss.github.io/retree/classes/_retreejs_core.ReactiveNode.html): Base class for derived dependencies, dependency comparison, and memoized computed values. - [Core README ownership section](https://github.com/ryanbliss/retree/tree/main/packages/retree-core#move-link-or-clone-existing-nodes): Examples for `Retree.move`, `Retree.link`, `@link`, `ReactiveNode.moveTo`, and `Retree.clone`. - [Core README select section](https://github.com/ryanbliss/retree/tree/main/packages/retree-core#select-derived-values): Examples for `Retree.select`, including when to use `listenerType: "treeChanged"`. - [@retreejs/query API](https://ryanbliss.github.io/retree/modules/_retreejs_query.html): Backend-agnostic query exports including `QueryNode`, `fetchQueryNode`, subscription-source interfaces, and reconcilers. - [@retreejs/devtools API](https://ryanbliss.github.io/retree/modules/_retreejs_devtools.html): DevTools exports including `connectReduxDevTools` and `createChangeLogTap`. - [@retreejs/react API](https://ryanbliss.github.io/retree/modules/_retreejs_react.html): React exports for stateful Retree nodes and trees. - [useNode](https://ryanbliss.github.io/retree/functions/_retreejs_react.useNode.html): React hook for subscribing to direct node changes with fine-grained re-rendering. - [useTree](https://ryanbliss.github.io/retree/functions/_retreejs_react.useTree.html): React hook for subscribing to node and descendant-tree changes. - [useRoot](https://ryanbliss.github.io/retree/functions/_retreejs_react.useRoot.html): React hook for creating and retaining a Retree root in a component. - [useRaw](https://ryanbliss.github.io/retree/functions/_retreejs_react.useRaw.html): React hook returning `[raw, toManaged]` for native-speed, proxy-free render reads with `useNode`-style invalidation. - [@retreejs/convex API](https://ryanbliss.github.io/retree/modules/_retreejs_convex.html): Convex exports for `BaseConvexNode`, `ConvexNode`, `ConvexQueryNode`, `ConvexPaginatedQueryNode`, `ConvexConnectionStateNode`, action and mutation helpers, optimistic update contexts, and reconcilers. - [BaseConvexNode class](https://ryanbliss.github.io/retree/classes/_retreejs_convex.BaseConvexNode.html): Base Retree node for classes that own a Convex client and need protected action, mutation, and one-off query helpers. - [ConvexNode class](https://ryanbliss.github.io/retree/classes/_retreejs_convex.ConvexNode.html): Base class for Retree nodes that own a Convex client and create typed query, paginated query, action, mutation, query-once, and connection-state helpers. - [ConvexQueryNode class](https://ryanbliss.github.io/retree/classes/_retreejs_convex.ConvexQueryNode.html): Reactive query node that subscribes to Convex query updates and exposes `state`, structured `result`, `updateArgs(...)`, skipping, errors, and optimistic updates. - [ConvexPaginatedQueryNode class](https://ryanbliss.github.io/retree/classes/_retreejs_convex.ConvexPaginatedQueryNode.html): Reactive paginated query node with aggregate page state and `loadMore(...)`. - [ConvexConnectionStateNode class](https://ryanbliss.github.io/retree/classes/_retreejs_convex.ConvexConnectionStateNode.html): Reactive node for Convex client connection state. - [@retreejs/react-convex API](https://ryanbliss.github.io/retree/modules/_retreejs_react_convex.html): React Convex adapter exports including `RetreeConvexReactClient`. ## Samples - [Core example](https://github.com/ryanbliss/retree/tree/main/samples/01.core-example): Minimal non-React Retree sample. - [React example](https://github.com/ryanbliss/retree/tree/main/samples/02.react-example): React sample app using Retree state. - [React recursion example](https://github.com/ryanbliss/retree/tree/main/samples/03.react-recursion): Recursive React tree sample using Retree. - [Convex React Next.js example](https://github.com/ryanbliss/retree/tree/main/samples/04.convex-react-nextjs): Full-stack Next.js sample with Convex query nodes, optimistic updates, error/retry state, and per-row `useNode` reactivity. ## Packages - [@retreejs/core on npm](https://www.npmjs.com/package/@retreejs/core): Core state-management package. - [@retreejs/react on npm](https://www.npmjs.com/package/@retreejs/react): React hooks package. - [@retreejs/query on npm](https://www.npmjs.com/package/@retreejs/query): Backend-agnostic async query node package. - [@retreejs/convex on npm](https://www.npmjs.com/package/@retreejs/convex): Convex query and mutation bindings package. - [@retreejs/react-convex on npm](https://www.npmjs.com/package/@retreejs/react-convex): Convex React client adapter for Retree Convex nodes. - [@retreejs/devtools on npm](https://www.npmjs.com/package/@retreejs/devtools): Redux DevTools bridge and change-log tap package. - [@retreejs/react-eslint-plugin on npm](https://www.npmjs.com/package/@retreejs/react-eslint-plugin): Typed ESLint rule for unobserved Retree reads in React components. ## Optional - [GitHub repository](https://github.com/ryanbliss/retree): Source code, issues, package workspace, and samples. - [Fluid Framework SharedTree](https://fluidframework.com/docs/data-structures/tree/): Related inspiration mentioned in the Retree docs. ## This site (https://www.retree.dev) Every guide below is also served as raw markdown for machine readers: - [quick-start](https://www.retree.dev/raw/docs/quick-start.md): raw markdown of https://www.retree.dev/docs/quick-start - [thinking-in-retree](https://www.retree.dev/raw/docs/thinking-in-retree.md): raw markdown of https://www.retree.dev/docs/thinking-in-retree - [common-pitfalls](https://www.retree.dev/raw/docs/common-pitfalls.md): raw markdown of https://www.retree.dev/docs/common-pitfalls - [react](https://www.retree.dev/raw/docs/react.md): raw markdown of https://www.retree.dev/docs/react - [react/use-root](https://www.retree.dev/raw/docs/react/use-root.md): raw markdown of https://www.retree.dev/docs/react/use-root - [react/use-node](https://www.retree.dev/raw/docs/react/use-node.md): raw markdown of https://www.retree.dev/docs/react/use-node - [react/use-tree](https://www.retree.dev/raw/docs/react/use-tree.md): raw markdown of https://www.retree.dev/docs/react/use-tree - [react/use-select](https://www.retree.dev/raw/docs/react/use-select.md): raw markdown of https://www.retree.dev/docs/react/use-select - [react/use-raw](https://www.retree.dev/raw/docs/react/use-raw.md): raw markdown of https://www.retree.dev/docs/react/use-raw - [react/eslint](https://www.retree.dev/raw/docs/react/eslint.md): raw markdown of https://www.retree.dev/docs/react/eslint - [events-and-subscriptions](https://www.retree.dev/raw/docs/events-and-subscriptions.md): raw markdown of https://www.retree.dev/docs/events-and-subscriptions - [effects-and-reactions](https://www.retree.dev/raw/docs/effects-and-reactions.md): raw markdown of https://www.retree.dev/docs/effects-and-reactions - [tree-operations](https://www.retree.dev/raw/docs/tree-operations.md): raw markdown of https://www.retree.dev/docs/tree-operations - [transactions](https://www.retree.dev/raw/docs/transactions.md): raw markdown of https://www.retree.dev/docs/transactions - [undo-redo](https://www.retree.dev/raw/docs/undo-redo.md): raw markdown of https://www.retree.dev/docs/undo-redo - [view-models](https://www.retree.dev/raw/docs/view-models.md): raw markdown of https://www.retree.dev/docs/view-models - [setup-and-decorators](https://www.retree.dev/raw/docs/setup-and-decorators.md): raw markdown of https://www.retree.dev/docs/setup-and-decorators - [select-semantics](https://www.retree.dev/raw/docs/select-semantics.md): raw markdown of https://www.retree.dev/docs/select-semantics - [performance](https://www.retree.dev/raw/docs/performance.md): raw markdown of https://www.retree.dev/docs/performance - [react-compiler](https://www.retree.dev/raw/docs/react-compiler.md): raw markdown of https://www.retree.dev/docs/react-compiler - [testing](https://www.retree.dev/raw/docs/testing.md): raw markdown of https://www.retree.dev/docs/testing - [devtools](https://www.retree.dev/raw/docs/devtools.md): raw markdown of https://www.retree.dev/docs/devtools - [convex](https://www.retree.dev/raw/docs/convex.md): raw markdown of https://www.retree.dev/docs/convex - [query](https://www.retree.dev/raw/docs/query.md): raw markdown of https://www.retree.dev/docs/query - [compatibility](https://www.retree.dev/raw/docs/compatibility.md): raw markdown of https://www.retree.dev/docs/compatibility - [migrate/mobx](https://www.retree.dev/raw/docs/migrate/mobx.md): raw markdown of https://www.retree.dev/docs/migrate/mobx - [migrate/zustand](https://www.retree.dev/raw/docs/migrate/zustand.md): raw markdown of https://www.retree.dev/docs/migrate/zustand - [migrate/redux](https://www.retree.dev/raw/docs/migrate/redux.md): raw markdown of https://www.retree.dev/docs/migrate/redux ### Generated API reference - [@retreejs/core reference](https://www.retree.dev/api/core): generated from TypeScript source on every deploy - [@retreejs/query reference](https://www.retree.dev/api/query): generated from TypeScript source on every deploy - [@retreejs/react reference](https://www.retree.dev/api/react): generated from TypeScript source on every deploy - [@retreejs/devtools reference](https://www.retree.dev/api/devtools): generated from TypeScript source on every deploy - [@retreejs/convex reference](https://www.retree.dev/api/convex): generated from TypeScript source on every deploy - [@retreejs/react-convex reference](https://www.retree.dev/api/react-convex): generated from TypeScript source on every deploy - [@retreejs/react-eslint-plugin reference](https://www.retree.dev/api/react-eslint-plugin): generated from TypeScript source on every deploy