component-refactoring
- Repo stars 149,183
- Author updated Live
- Author repo langflow
- Domain
- Data
- Compatible agents
-
- Claude Code
- Cursor
- Cline
- Codex
- Windsurf
- Gemini CLI
- +20
- Trust score
- 88 / 100 · community maintained
- Author / version / license
- @langflow-ai · no license declared
- Token usage
- Lean
- Setup complexity
- Guided setup
- External API key
- Not required
- Operating systems
- macOS · Linux · Windows
- Runtime requirements
- Node.js
- Permissions
-
- Read-only
- Write / modify
- Shell exec
- Network behavior
- Local-only
- Install commands
- 26 variants
Profile is derived at build time from SKILL.md and install vectors. Subject to drift from author intent.
Heads up: 未限定 allowed-tools,默认拥有全部工具权限。
---
name: component-refactoring
description: Refactor high-complexity React components in Langflow frontend. Use when manual complexity asses…
category: data
runtime: Node.js
---
# component-refactoring output preview
## PART A: Task fit
- Use case: Refactor high-complexity React components in Langflow frontend. Use when manual complexity assessment shows complexity > 50 or lineCount > 300, when the user asks for code splitting, hook extraction, or complexity reduction; avoid for simple/well-structured components, third-party wrappers, or when the user explicitly wants testing without refactoring..
- Inputs: target material, constraints, expected output, and acceptance criteria.
- Evidence boundary: follow “Quick Reference / Commands (run from src/frontend/) / Manual Complexity Assessment” and do not present inference as author intent.
## PART B: Execution result
- **01** The card summarizes the use case; runtime output centers on “Refactor high-complexity React components in Langflow frontend. Use when manual complexity assessment shows complexity > 50 or lineCount > 300, when the user asks for code splitting, hook extraction, or complexity reduction; avoid for simple/well-structured components, third-party wrappers, or when the user explicitly wants testing without refactoring.”.
- **02** When the source has headings, the agent prioritizes “Quick Reference / Commands (run from src/frontend/) / Manual Complexity Assessment” so the result follows the author’s structure.
- **03** Typical output includes task judgment, concrete steps, required commands or file edits, validation, and follow-up options.
- **04** Risk context follows the fingerprint: read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
## Running Rules
- read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
- Validate with a small sample before expanding scope.
- Return the result, validation criteria, and next iteration options. The source does not require a stable slash command. After installation, invoke the skill by name and describe the task.
Name target files or source material, expected output, forbidden changes, and whether network or shell access is allowed. Permission fingerprint: read files, write/modify files, run shell commands.
Start with a small task and check whether the result follows “Quick Reference / Commands (run from src/frontend/) / Manual Complexity Assessment”. Inspect diffs, logs, previews, or tests before expanding scope.
Confirm the final output includes a concrete result, evidence, and next action. If it stays generic, tighten inputs, boundaries, and acceptance criteria.
---
name: component-refactoring
description: Refactor high-complexity React components in Langflow frontend. Use when manual complexity asses…
category: data
source: langflow-ai/langflow
---
# component-refactoring
## When to use
- Refactor high-complexity React components in Langflow frontend. Use when manual complexity assessment shows complexity…
- Use it when the task has clear inputs, repeatable steps, and validation criteria.
## What to provide
- Target material, scope, expected result, and forbidden changes.
- Whether network, commands, file writes, or external services are allowed.
## Execution rules
- Organize steps around “Quick Reference / Commands (run from src/frontend/) / Manual Complexity Assessment” and keep inference separate from source facts.
- read files, write/modify files, run shell commands; mostly runs locally; usually needs no extra API key.
- Validate with a small sample before expanding the task.
## Output requirements
- Return the deliverable, key evidence, validation method, and next action.
- Mark missing information as unknown; do not invent commands, platforms, or dependencies. The author source anchors workflow facts; repository files anchor sources and commands; Fluxly only adds fit, limitations, and quality judgment.
skill "component-refactoring" {
input -> user goal + target files + boundaries + acceptance criteria
context -> Quick Reference / Commands (run from src/frontend/) / Manual Complexity Assessment
rules -> SKILL.md triggers / order / output contract
runtime -> Node.js | read files, write/modify files, run shell commands | mostly runs locally
guardrails -> usually needs no extra API key + small-sample validation + diff/log review
output -> copyable result + checklist + next iteration
} Langflow Component Refactoring Skill
Refactor high-complexity React components in the Langflow frontend codebase with the patterns and workflow below.
Complexity Threshold: Components with complexity > 50 (measured manually by counting conditionals, nesting levels, and lines) should be refactored before testing.
Quick Reference
Commands (run from src/frontend/)
cd src/frontend
# Lint with Biome
npm run lint
# Type checking
npm run type-check
# Run tests
npm test
Manual Complexity Assessment
Since Langflow does not have automated complexity analysis tools, assess components manually:
- Count conditionals: Each
if/else,switch/case, ternary,&&/||chain adds +1. - Count nesting levels: Each level of nesting within conditionals or loops adds +1.
- Count total lines: Target < 300 lines per component file.
- Count state hooks: More than 5
useStatecalls suggests hook extraction. - Count effects: More than 3
useEffectcalls suggests effect consolidation.
Complexity Score Interpretation
| Score | Level | Action |
|---|---|---|
| 0-25 | Simple | Ready for testing |
| 26-50 | Medium | Consider minor refactoring |
| 51-75 | Complex | Refactor before testing |
| 76-100 | Very Complex | Must refactor |
Core Refactoring Patterns
Pattern 1: Extract Custom Hooks
When: Component has complex state management, multiple useState/useEffect, or business logic mixed with UI.
Langflow Convention: Place hooks in a hooks/ subdirectory or alongside the component as use-<feature>.ts. Langflow uses kebab-case filenames with use- prefix.
// Before: Complex state logic in component
const FlowPage: FC = () => {
const [nodes, setNodes] = useState<Node[]>([])
const [edges, setEdges] = useState<Edge[]>([])
const [buildStatus, setBuildStatus] = useState<BuildStatus>(BuildStatus.IDLE)
// 50+ lines of state management logic...
return <div>...</div>
}
// After: Extract to custom hook
// hooks/use-flow-state.ts
export const useFlowState = (flowId: string) => {
const [nodes, setNodes] = useState<Node[]>([])
const [edges, setEdges] = useState<Edge[]>([])
const [buildStatus, setBuildStatus] = useState<BuildStatus>(BuildStatus.IDLE)
// Related state management logic here
return { nodes, setNodes, edges, setEdges, buildStatus, setBuildStatus }
}
// Component becomes cleaner
const FlowPage: FC = () => {
const { nodes, setNodes, edges, setEdges } = useFlowState(flowId)
return <div>...</div>
}
Langflow Examples:
src/frontend/src/hooks/use-add-component.tssrc/frontend/src/hooks/use-unsaved-changes.tssrc/frontend/src/hooks/use-refresh-model-inputs.ts
Pattern 2: Extract Sub-Components
When: Single component has multiple UI sections, conditional rendering blocks, or repeated patterns.
Langflow Convention: Place sub-components in subdirectories or as separate files in the same directory. UI primitives go in components/ui/, domain components in components/core/, reusable components in components/common/.
// Before: Monolithic JSX with multiple sections
const GenericNode = () => {
return (
<div>
{/* 100 lines of header UI */}
{/* 100 lines of parameter fields */}
{/* 100 lines of output handles */}
</div>
)
}
// After: Split into focused components
// CustomNodes/GenericNode/
// generic-node.tsx (orchestration only — kebab-case, descriptive name)
// components/
// node-header.tsx
// node-parameters.tsx
// node-outputs.tsx
const GenericNode = () => {
return (
<div>
<NodeHeader nodeData={data} />
<NodeParameters fields={fields} />
<NodeOutputs outputs={outputs} />
</div>
)
}
Langflow Examples:
src/frontend/src/CustomNodes/GenericNode/components/src/frontend/src/components/core/src/frontend/src/components/ui/
Pattern 3: Simplify Conditional Logic
When: Deep nesting (> 3 levels), complex ternaries, or multiple if/else chains.
// Before: Deeply nested conditionals
const getFieldComponent = (field: InputFieldType) => {
if (field.type === "str") {
if (field.multiline) {
return <TextAreaComponent />
} else if (field.password) {
return <PasswordInput />
} else if (field.options?.length) {
return <Dropdown options={field.options} />
} else {
return <InputComponent />
}
} else if (field.type === "int") {
return <IntComponent />
} else if (field.type === "float") {
return <FloatComponent />
}
return null
}
// After: Use lookup tables + early returns
const FIELD_COMPONENT_MAP: Record<string, FC<FieldProps>> = {
int: IntComponent,
float: FloatComponent,
bool: ToggleComponent,
code: CodeAreaComponent,
}
const STR_VARIANT_MAP: Record<string, FC<FieldProps>> = {
multiline: TextAreaComponent,
password: PasswordInput,
options: Dropdown,
}
const getFieldComponent = (field: InputFieldType) => {
if (field.type !== "str") {
const Component = FIELD_COMPONENT_MAP[field.type]
return Component ? <Component {...field} /> : null
}
const variant = field.multiline ? "multiline"
: field.password ? "password"
: field.options?.length ? "options"
: "default"
const Component = STR_VARIANT_MAP[variant] ?? InputComponent
return <Component {...field} />
}
Pattern 4: Extract API/Data Logic
When: Component directly handles API calls, data transformation, or complex async operations.
Langflow Convention:
- This skill is for component decomposition, not query/mutation design.
- When refactoring data fetching, use
frontend-query-mutationfor query patterns,UseRequestProcessor, cache invalidation, and mutation error handling. - Do not create thin passthrough
useQuerywrappers during refactoring; only extract a custom hook when it truly orchestrates multiple queries/mutations or shared derived state. - API hooks live in
controllers/API/queries/{domain}/.
Langflow Examples:
src/frontend/src/controllers/API/queries/flows/use-post-add-flow.tssrc/frontend/src/controllers/API/queries/variables/use-get-global-variables.tssrc/frontend/src/controllers/API/queries/folders/use-get-folders.ts
Pattern 5: Extract Modal/Dialog Management
When: Component manages multiple modals with complex open/close states.
Langflow Convention: Modals should be extracted with their state management.
// Before: Multiple modal states in component
const FlowToolbar = () => {
const [showExportModal, setShowExportModal] = useState(false)
const [showShareModal, setShowShareModal] = useState(false)
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
const [showApiModal, setShowApiModal] = useState(false)
// 5+ more modal states...
}
// After: Extract to modal management hook
type ModalType = "export" | "share" | "delete" | "api" | null
const useFlowToolbarModals = () => {
const [activeModal, setActiveModal] = useState<ModalType>(null)
const openModal = useCallback((type: ModalType) => setActiveModal(type), [])
const closeModal = useCallback(() => setActiveModal(null), [])
return {
activeModal,
openModal,
closeModal,
isOpen: (type: ModalType) => activeModal === type,
}
}
Pattern 6: Extract Form Logic
When: Complex form validation, submission handling, or field transformation.
Langflow Convention: Extract form state and validation into hooks.
// Extract form validation and submission
const useFlowSettingsForm = (initialValues: FlowSettings) => {
const [values, setValues] = useState(initialValues)
const [errors, setErrors] = useState<Record<string, string>>({})
const validate = useCallback(() => {
const newErrors: Record<string, string> = {}
if (!values.name?.trim()) newErrors.name = "Name is required"
if (values.endpoint_name && !/^[a-z0-9-]+$/.test(values.endpoint_name)) {
newErrors.endpoint_name = "Must be lowercase alphanumeric with hyphens"
}
setErrors(newErrors)
return Object.keys(newErrors).length === 0
}, [values])
const handleChange = useCallback((field: string, value: any) => {
setValues((prev) => ({ ...prev, [field]: value }))
}, [])
return { values, errors, validate, handleChange }
}
Langflow-Specific Refactoring Guidelines
1. Zustand Store Selectors
When: Component reads many values from a Zustand store, causing unnecessary re-renders.
// Before: Selecting too many values
const Component = () => {
const flowStore = useFlowStore()
// Component re-renders on ANY store change
}
// After: Use individual selectors
const Component = () => {
const nodes = useFlowStore((state) => state.nodes)
const edges = useFlowStore((state) => state.edges)
// Component only re-renders when nodes or edges change
}
Langflow Reference: All stores in src/frontend/src/stores/ follow this selector pattern.
2. Custom Node Components
When: Refactoring flow node components (CustomNodes/GenericNode/).
Conventions:
- Keep node logic in custom hooks
- Extract parameter rendering to separate components
- Use the existing
components/subdirectory for sub-components
CustomNodes/GenericNode/
generic-node.tsx # Node registration and main render (kebab-case, NOT index.tsx)
components/
handle-render.tsx # Handle rendering
node-description.tsx # Node description display
node-input-field.tsx # Input field rendering
node-name.tsx # Node name display
node-output-field.tsx # Output field rendering
node-status.tsx # Build status display
3. Flow Canvas Components
When: Refactoring components related to the flow editor canvas.
Conventions:
@xyflow/reactv12 is the canvas library- Keep canvas event handlers separate from UI rendering
- Use
useFlowStorefor flow state management - Use
useFlowsManagerStorefor multi-flow management
4. API Query Hook Components
When: Refactoring components that consume API data.
Conventions:
- Use existing query hooks from
controllers/API/queries/ - Access
UseRequestProcessorfor new queries/mutations - Use query key arrays like
["useGetGlobalVariables"]for cache management - Cache invalidation belongs in mutation
onSettledcallbacks
Refactoring Workflow
Step 1: Assess Complexity
Manually count:
- Total conditionals (if/else, switch, ternary, &&/||)
- Maximum nesting depth
- Total lines of code
- Number of useState/useEffect hooks
- Number of distinct UI sections
Step 2: Plan
Create a refactoring plan based on detected features:
| Detected Feature | Refactoring Action |
|---|---|
5+ useState hooks with related state |
Extract custom hook |
| API calls in component body | Extract to query hook |
| 3+ event handlers with logic | Extract event handlers to hook |
| 300+ lines | Split into sub-components |
| Deep conditional nesting (>3) | Simplify conditional logic |
| Multiple modal states | Extract modal management |
Step 3: Execute Incrementally
- Extract one piece at a time
- Run lint, type-check, and tests after each extraction
- Verify functionality before next step
For each extraction:
1. Extract code
2. Run: npm run lint
3. Run: npm run type-check
4. Run: npm test
5. Test functionality manually
6. PASS? -> Next extraction
FAIL? -> Fix before continuing
Step 4: Verify
After refactoring, re-assess complexity manually:
- Target complexity < 50
- Target line count < 300
- Target max nesting depth <= 3
- Target max function length < 30 lines
Common Mistakes to Avoid
Over-Engineering
// Too many tiny hooks
const useButtonText = () => useState("Click")
const useButtonDisabled = () => useState(false)
const useButtonLoading = () => useState(false)
// Cohesive hook with related state
const useButtonState = () => {
const [text, setText] = useState("Click")
const [disabled, setDisabled] = useState(false)
const [loading, setLoading] = useState(false)
return { text, setText, disabled, setDisabled, loading, setLoading }
}
Breaking Existing Patterns
- Follow existing directory structures in
components/ui/,components/core/,components/common/ - Maintain naming conventions (kebab-case files, PascalCase components)
- Preserve export patterns for compatibility
- Keep Zustand store selector patterns consistent
Premature Abstraction
- Only extract when there is clear complexity benefit
- Do not create abstractions for single-use code
- Keep refactored code in the same domain area
Bypassing UseRequestProcessor
- Do not call
useQueryoruseMutationdirectly for API calls - Always use the
UseRequestProcessorpattern for consistency with retry and invalidation logic - See
frontend-query-mutationskill for API hook patterns
References
Langflow Codebase Examples
- Hook extraction:
src/frontend/src/hooks/ - Component splitting:
src/frontend/src/CustomNodes/GenericNode/components/ - UI components:
src/frontend/src/components/ui/ - Core components:
src/frontend/src/components/core/ - Common components:
src/frontend/src/components/common/ - API query hooks:
src/frontend/src/controllers/API/queries/ - Zustand stores:
src/frontend/src/stores/
Related Skills
frontend-query-mutation- For API query and mutation patternsfrontend-testing- For testing refactored components
Decide Fit First
Design Intent
How To Use It
Boundaries And Review