Skip to main content

component-state

Guides state management, component logic, and hook composition in CloudBeaver React components. Use when creating, changing, reviewing, or extracting component behavior, state, or hooks.

Source facts

Repository
dbeaver/cloudbeaver
Last source activity
November 2, 2026 at 20:48
Detected SKILL.md language
English
Stars
5,223
Forks
576

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
component-state
description
Guides state management, component logic, and hook composition in CloudBeaver React components. Use when creating, changing, reviewing, or extracting component behavior, state, or hooks.
# Component state Keep components easy to read: call hooks, connect their results, render UI. - Move related state, derived values, and operations into a named hook. Several state fields, handlers, and effects for one task are a sign to extract it. A single local UI flag can stay. - Extract complex logic into a separate hook even when it has no observable state. It can stay in the component when it is the component's direct responsibility and its only piece of logic. - Give each hook one job. Do not move a large component into one equally large hook. - If a hook owns observable state, use `useObservableRef` from `@cloudbeaver/core-blocks`. - Return the state object itself, with values and operations. Do not spread it into a new object or return snapshots of its observable fields. ## useObservableRef ```ts import { action, computed, observable } from 'mobx'; import { useObservableRef } from '@cloudbeaver/core-blocks'; function useSearchState(items: readonly string[]) { return useObservableRef( () => ({ query: '', get filteredItems(): readonly string[] { return this.items.filter(item => item.includes(this.query)); }, setQuery(query: string) { this.query = query; }, }), { query: observable.ref, items: observable.ref, filteredItems: computed, setQuery: action.bound, }, { items }, ); } ``` - Read changing inputs through `this` and pass them in the third argument. A closure in the factory can keep the first render's values. - Keep editable local fields out of the update object: it overwrites local changes. Pass `false` when there are no inputs to update; omitting the third argument reapplies values from `init`. - After `await`, wrap observable changes in `runInAction`; an action does not cover the continuation. - Read observable fields inside an `observer` render or a tracked getter, not as snapshots destructured before that read. Otherwise MobX cannot track the source field. ## Compose hooks Pass one hook's result into the next. Keep the connection visible instead of copying values between independent states with effects. For example: ```ts const source = useItemsSource(projectId); const search = useItemsSearch(source); const selection = useItemsSelection(search); ``` The receiving hook reads the source object in its getters and operations. If that source can be replaced, pass it through the third argument of `useObservableRef`. Do not copy its current fields into a second state. This keeps one owner for each value and preserves reactivity. Keep hooks unconditional and at the top level. If the wiring itself grows, extract a composing hook. A component coordinating several responsibilities should show the flow, not implement all their state transitions.
View on GitHub