Refactor high-complexity React components in Dify frontend. Use when `pnpm analyze-component --json` shows complexity > 50 or lineCount > 300, when the user asks for code splitting, hook extraction, or complexity reduction, or when `pnpm analyze-component` warns to refactor before testing; avoid for simple/well-structured components, third-party wrappers, or when the user explicitly wants testing without refactoring.
Use the skills CLI to install this skill with one command. Auto-detects all installed AI assistants.
Method 1 - skills CLI
npx skills i langgenius/dify/.agents/skills/component-refactoringMethod 2 - openskills (supports sync & update)
npx openskills install langgenius/difyAuto-detects Claude Code, Cursor, Codex CLI, Gemini CLI, and more. One install, works everywhere.
Installation Path
Download and extract to one of the following locations:
No setup needed. Let our cloud agents run this skill for you.
Select Provider
Select Model
Best for coding tasks
Environment setup included
Refactor high-complexity React components in the Dify frontend codebase with the patterns and workflow below.
Complexity Threshold: Components with complexity > 50 (measured by
pnpm analyze-component) should be refactored before testing.
web/)Use paths relative to web/ (e.g., app/components/...).
Use refactor-component for refactoring prompts and analyze-component for testing prompts and metrics.
cd web
# Generate refactoring prompt
pnpm refactor-component <path>
# Output refactoring analysis as JSON
pnpm refactor-component <path> --json
# Generate testing prompt (after refactoring)
pnpm analyze-component <path>
# Output testing analysis as JSON
pnpm analyze-component <path> --json# Analyze component complexity
pnpm analyze-component <path> --json
# Key metrics to check:
# - complexity: normalized score 0-100 (target < 50)
# - maxComplexity: highest single function complexity
# - lineCount: total lines (target < 300)| 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 |
When: Component has complex state management, multiple useState/useEffect, or business logic mixed with UI.
Dify Convention: Place hooks in a hooks/ subdirectory or alongside the component as use-<feature>.ts.
// ❌ Before: Complex state logic in component
const Configuration: FC = () => {
const [modelConfig, setModelConfig] = useState<ModelConfig>(...)
const [datasetConfigs,
Dify Examples:
web/app/components/app/configuration/hooks/use-advanced-prompt-config.tsweb/app/components/app/configuration/debug/hooks.tsxweb/app/components/workflow/hooks/use-workflow.tsWhen: Single component has multiple UI sections, conditional rendering blocks, or repeated patterns.
Dify Convention: Place sub-components in subdirectories or as separate files in the same directory.
// ❌ Before: Monolithic JSX with multiple sections
const AppInfo = () => {
return (
<div>
{/* 100 lines of header UI */}
{/* 100 lines of operations UI */}
{/* 100 lines of modals */}
</div>
)
Dify Examples:
web/app/components/app/configuration/ directory structureweb/app/components/workflow/nodes/ per-node organizationWhen: Deep nesting (> 3 levels), complex ternaries, or multiple if/else chains.
// ❌ Before: Deeply nested conditionals
const Template = useMemo(() => {
if (appDetail?.mode === AppModeEnum.CHAT) {
switch (locale) {
case LanguagesSupported[1]:
return <TemplateChatZh
When: Component directly handles API calls, data transformation, or complex async operations.
Dify Convention: Use @tanstack/react-query hooks from web/service/use-*.ts or create custom data hooks.
// ❌ Before: API logic in component
const MCPServiceCard = () => {
const [basicAppConfig, setBasicAppConfig] = useState({})
useEffect(() => {
if (isBasicApp &&
React Query Best Practices in Dify:
NAME_SPACE for query key organizationenabled option for conditional fetchingselect for data transformationuseInvalidXxxDify Examples:
web/service/use-workflow.tsweb/service/use-common.tsweb/service/knowledge/use-dataset.tsweb/service/knowledge/use-document.tsWhen: Component manages multiple modals with complex open/close states.
Dify Convention: Modals should be extracted with their state management.
// ❌ Before: Multiple modal states in component
const AppInfo = () => {
const [showEditModal, setShowEditModal] = useState(false)
const [showDuplicateModal, setShowDuplicateModal] = useState
When: Complex form validation, submission handling, or field transformation.
Dify Convention: Use @tanstack/react-form patterns from web/app/components/base/form/.
// ✅ Use existing form infrastructure
import { useAppForm } from '@/app/components/base/form'
const ConfigForm = () => {
const form = useAppForm({
defaultValues: { name: '', description: '' },
onSubmit: handleSubmit,
})
return <form.Provider>...</form.Provider
When: Component provides complex context values with multiple states.
// ❌ Before: Large context value object
const value = {
appId, isAPIKeySet, isTrailFinished, mode, modelModeType,
promptMode, isAdvancedMode, isAgent, isOpenAI, isFunctionCall,
// 50+ more properties...
}
return <ConfigContext.Provider value={value}>...</ConfigContext.Provider>
// ✅ After: Split into domain-specific contexts
<ModelConfigProvider value={modelConfigValue}
Dify Reference: web/context/ directory structure
When: Refactoring workflow node components (web/app/components/workflow/nodes/).
Conventions:
use-interactions.ts_base components for common patternsnodes/<node-type>/
├── index.tsx # Node registration
├── node.tsx # Node visual component
├── panel.tsx # Configuration panel
├── use-interactions.ts # Node-specific hooks
└── types.ts # Type definitions
When: Refactoring app configuration components.
Conventions:
web/app/components/app/configuration/When: Refactoring tool-related components (web/app/components/tools/).
Conventions:
web/service/use-tools.tspnpm refactor-component <path>This command will:
pnpm analyze-component <path> --jsonIdentify:
Create a refactoring plan based on detected features:
| Detected Feature | Refactoring Action |
|---|---|
hasState: true + hasEffects: true | Extract custom hook |
hasAPI: true | Extract data/service hook |
hasEvents: true (many) | Extract event handlers |
lineCount > 300 | Split into sub-components |
maxComplexity > 50 | Simplify conditional logic |
For each extraction:
┌────────────────────────────────────────┐
│ 1. Extract code │
│ 2. Run: pnpm lint:fix │
│ 3. Run: pnpm type-check:tsgo │
│ 4. Run: pnpm test │
│ 5. Test functionality manually │
│ 6. PASS? → Next extraction │
│ FAIL? → Fix before continuing │
└────────────────────────────────────────┘
After refactoring:
# Re-run refactor command to verify improvements
pnpm refactor-component <path>
# If complexity < 25 and lines < 200, you'll see:
# ✅ COMPONENT IS WELL-STRUCTURED
# For detailed metrics:
pnpm analyze-component <path> --json
# Target metrics:
# - complexity < 50
# - lineCount < 300
# - maxComplexity < 30// ❌ Too many tiny hooks
const useButtonText = () => useState('Click')
const useButtonDisabled = () => useState(false)
const useButtonLoading = () => useState(false)
// ✅ Cohesive hook with related state
const useButtonState =
web/app/components/app/configuration/hooks/web/app/components/app/configuration/web/service/use-*.tsweb/app/components/workflow/hooks/web/app/components/base/form/frontend-testing - For testing refactored componentsweb/docs/test.md - Testing specification