AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Component Refactoring

skill-lien0219-openxflow-component-refactoring · by lien0219

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.

No reviews yet
0 installs
35 views
0.0% view→install

Install

$ agentstack add skill-lien0219-openxflow-component-refactoring

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access No
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-lien0219-openxflow-component-refactoring)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
2mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Component Refactoring? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

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:

  1. Count conditionals: Each if/else, switch/case, ternary, &&/|| chain adds +1.
  2. Count nesting levels: Each level of nesting within conditionals or loops adds +1.
  3. Count total lines: Target .ts. Langflow uses kebab-case filenames with use-` prefix.
// Before: Complex state logic in component
const FlowPage: FC = () => {
  const [nodes, setNodes] = useState([])
  const [edges, setEdges] = useState([])
  const [buildStatus, setBuildStatus] = useState(BuildStatus.IDLE)

  // 50+ lines of state management logic...

  return ...
}

// After: Extract to custom hook
// hooks/use-flow-state.ts
export const useFlowState = (flowId: string) => {
  const [nodes, setNodes] = useState([])
  const [edges, setEdges] = useState([])
  const [buildStatus, setBuildStatus] = useState(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 ...
}

Langflow Examples:

  • src/frontend/src/hooks/use-add-component.ts
  • src/frontend/src/hooks/use-unsaved-changes.ts
  • src/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 (
    
      {/* 100 lines of header UI */}
      {/* 100 lines of parameter fields */}
      {/* 100 lines of output handles */}
    
  )
}

// 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 (
    
      
      
      
    
  )
}

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 
    } else if (field.password) {
      return 
    } else if (field.options?.length) {
      return 
    } else {
      return 
    }
  } else if (field.type === "int") {
    return 
  } else if (field.type === "float") {
    return 
  }
  return null
}

// After: Use lookup tables + early returns
const FIELD_COMPONENT_MAP: Record> = {
  int: IntComponent,
  float: FloatComponent,
  bool: ToggleComponent,
  code: CodeAreaComponent,
}

const STR_VARIANT_MAP: Record> = {
  multiline: TextAreaComponent,
  password: PasswordInput,
  options: Dropdown,
}

const getFieldComponent = (field: InputFieldType) => {
  if (field.type !== "str") {
    const Component = FIELD_COMPONENT_MAP[field.type]
    return Component ?  : null
  }

  const variant = field.multiline ? "multiline"
    : field.password ? "password"
    : field.options?.length ? "options"
    : "default"

  const Component = STR_VARIANT_MAP[variant] ?? InputComponent
  return 
}

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-mutation for query patterns, UseRequestProcessor, cache invalidation, and mutation error handling.
  • Do not create thin passthrough useQuery wrappers 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.ts
  • src/frontend/src/controllers/API/queries/variables/use-get-global-variables.ts
  • src/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(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>({})

  const validate = useCallback(() => {
    const newErrors: Record = {}
    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/react v12 is the canvas library
  • Keep canvas event handlers separate from UI rendering
  • Use useFlowStore for flow state management
  • Use useFlowsManagerStore for 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 UseRequestProcessor for new queries/mutations
  • Use query key arrays like ["useGetGlobalVariables"] for cache management
  • Cache invalidation belongs in mutation onSettled callbacks

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

  1. Extract one piece at a time
  2. Run lint, type-check, and tests after each extraction
  3. 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 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 `useQuery` or `useMutation` directly for API calls
- Always use the `UseRequestProcessor` pattern for consistency with retry and invalidation logic
- See `frontend-query-mutation` skill 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 patterns
- `frontend-testing` - For testing refactored components

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [lien0219](https://github.com/lien0219)
- **Source:** [lien0219/openxflow](https://github.com/lien0219/openxflow)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.