component-refactoring

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Dify Component Refactoring Skill

Dify 组件重构技能

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.
按照以下模式和工作流,重构Dify前端代码库中的高复杂度React组件。
复杂度阈值
pnpm analyze-component
测得复杂度>50的组件需在测试前完成重构。

Quick Reference

快速参考

Commands (run from
web/
)

命令(从
web/
目录执行)

Use paths relative to
web/
(e.g.,
app/components/...
). Use
refactor-component
for refactoring prompts and
analyze-component
for testing prompts and metrics.
bash
cd web
使用相对于
web/
的路径(例如
app/components/...
)。 使用
refactor-component
生成重构提示,使用
analyze-component
生成测试提示和指标。
bash
cd web

Generate refactoring prompt

生成重构提示

pnpm refactor-component <path>
pnpm refactor-component <path>

Output refactoring analysis as JSON

以JSON格式输出重构分析结果

pnpm refactor-component <path> --json
pnpm refactor-component <path> --json

Generate testing prompt (after refactoring)

生成测试提示(重构后执行)

pnpm analyze-component <path>
pnpm analyze-component <path>

Output testing analysis as JSON

以JSON格式输出测试分析结果

pnpm analyze-component <path> --json
undefined
pnpm analyze-component <path> --json
undefined

Complexity Analysis

复杂度分析

bash
undefined
bash
undefined

Analyze component complexity

分析组件复杂度

pnpm analyze-component <path> --json
pnpm analyze-component <path> --json

Key metrics to check:

需要关注的关键指标:

- complexity: normalized score 0-100 (target < 50)

- complexity: 标准化分数0-100(目标<50)

- maxComplexity: highest single function complexity

- maxComplexity: 单个函数的最高复杂度

- lineCount: total lines (target < 300)

- lineCount: 总代码行数(目标<300)

undefined
undefined

Complexity Score Interpretation

复杂度分数解读

ScoreLevelAction
0-25🟢 SimpleReady for testing
26-50🟡 MediumConsider minor refactoring
51-75🟠 ComplexRefactor before testing
76-100🔴 Very ComplexMust refactor
分数级别操作建议
0-25🟢 简单可直接测试
26-50🟡 中等考虑小幅重构
51-75🟠 复杂测试前必须重构
76-100🔴 极高复杂度必须重构

Core Refactoring Patterns

核心重构模式

Pattern 1: Extract Custom Hooks

模式1:提取自定义Hook

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
.
typescript
// ❌ Before: Complex state logic in component
const Configuration: FC = () => {
  const [modelConfig, setModelConfig] = useState<ModelConfig>(...)
  const [datasetConfigs, setDatasetConfigs] = useState<DatasetConfigs>(...)
  const [completionParams, setCompletionParams] = useState<FormValue>({})
  
  // 50+ lines of state management logic...
  
  return <div>...</div>
}

// ✅ After: Extract to custom hook
// hooks/use-model-config.ts
export const useModelConfig = (appId: string) => {
  const [modelConfig, setModelConfig] = useState<ModelConfig>(...)
  const [completionParams, setCompletionParams] = useState<FormValue>({})
  
  // Related state management logic here
  
  return { modelConfig, setModelConfig, completionParams, setCompletionParams }
}

// Component becomes cleaner
const Configuration: FC = () => {
  const { modelConfig, setModelConfig } = useModelConfig(appId)
  return <div>...</div>
}
Dify Examples:
  • web/app/components/app/configuration/hooks/use-advanced-prompt-config.ts
  • web/app/components/app/configuration/debug/hooks.tsx
  • web/app/components/workflow/hooks/use-workflow.ts
适用场景:组件包含复杂状态管理、多个
useState
/
useEffect
,或业务逻辑与UI代码混合。
Dify 约定:将Hook放置在
hooks/
子目录中,或与组件同级命名为
use-<feature>.ts
typescript
// ❌ 重构前:组件内包含复杂状态逻辑
const Configuration: FC = () => {
  const [modelConfig, setModelConfig] = useState<ModelConfig>(...)
  const [datasetConfigs, setDatasetConfigs] = useState<DatasetConfigs>(...)
  const [completionParams, setCompletionParams] = useState<FormValue>({})
  
  // 50+行状态管理逻辑...
  
  return <div>...</div>
}

// ✅ 重构后:提取为自定义Hook
// hooks/use-model-config.ts
export const useModelConfig = (appId: string) => {
  const [modelConfig, setModelConfig] = useState<ModelConfig>(...)
  const [completionParams, setCompletionParams] = useState<FormValue>({})
  
  // 相关状态管理逻辑在此处
  
  return { modelConfig, setModelConfig, completionParams, setCompletionParams }
}

// 组件变得更简洁
const Configuration: FC = () => {
  const { modelConfig, setModelConfig } = useModelConfig(appId)
  return <div>...</div>
}
Dify 示例:
  • web/app/components/app/configuration/hooks/use-advanced-prompt-config.ts
  • web/app/components/app/configuration/debug/hooks.tsx
  • web/app/components/workflow/hooks/use-workflow.ts

Pattern 2: Extract Sub-Components

模式2:提取子组件

When: 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.
typescript
// ❌ 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>
  )
}

// ✅ After: Split into focused components
// app-info/
//   ├── index.tsx           (orchestration only)
//   ├── app-header.tsx      (header UI)
//   ├── app-operations.tsx  (operations UI)
//   └── app-modals.tsx      (modal management)

const AppInfo = () => {
  const { showModal, setShowModal } = useAppInfoModals()
  
  return (
    <div>
      <AppHeader appDetail={appDetail} />
      <AppOperations onAction={handleAction} />
      <AppModals show={showModal} onClose={() => setShowModal(null)} />
    </div>
  )
}
Dify Examples:
  • web/app/components/app/configuration/
    directory structure
  • web/app/components/workflow/nodes/
    per-node organization
适用场景:单个组件包含多个UI区块、条件渲染块或重复代码模式。
Dify 约定:将子组件放置在子目录中,或与组件同级分为独立文件。
typescript
// ❌ 重构前:包含多个区块的单体JSX
const AppInfo = () => {
  return (
    <div>
      {/* 100行头部UI代码 */}
      {/* 100行操作区UI代码 */}
      {/* 100行模态框代码 */}
    </div>
  )
}

// ✅ 重构后:拆分为专注单一职责的组件
// app-info/
//   ├── index.tsx           (仅负责组件编排)
//   ├── app-header.tsx      (头部UI)
//   ├── app-operations.tsx  (操作区UI)
//   └── app-modals.tsx      (模态框管理)

const AppInfo = () => {
  const { showModal, setShowModal } = useAppInfoModals()
  
  return (
    <div>
      <AppHeader appDetail={appDetail} />
      <AppOperations onAction={handleAction} />
      <AppModals show={showModal} onClose={() => setShowModal(null)} />
    </div>
  )
}
Dify 示例:
  • web/app/components/app/configuration/
    目录结构
  • web/app/components/workflow/nodes/
    按节点类型组织

Pattern 3: Simplify Conditional Logic

模式3:简化条件逻辑

When: Deep nesting (> 3 levels), complex ternaries, or multiple
if/else
chains.
typescript
// ❌ Before: Deeply nested conditionals
const Template = useMemo(() => {
  if (appDetail?.mode === AppModeEnum.CHAT) {
    switch (locale) {
      case LanguagesSupported[1]:
        return <TemplateChatZh />
      case LanguagesSupported[7]:
        return <TemplateChatJa />
      default:
        return <TemplateChatEn />
    }
  }
  if (appDetail?.mode === AppModeEnum.ADVANCED_CHAT) {
    // Another 15 lines...
  }
  // More conditions...
}, [appDetail, locale])

// ✅ After: Use lookup tables + early returns
const TEMPLATE_MAP = {
  [AppModeEnum.CHAT]: {
    [LanguagesSupported[1]]: TemplateChatZh,
    [LanguagesSupported[7]]: TemplateChatJa,
    default: TemplateChatEn,
  },
  [AppModeEnum.ADVANCED_CHAT]: {
    [LanguagesSupported[1]]: TemplateAdvancedChatZh,
    // ...
  },
}

const Template = useMemo(() => {
  const modeTemplates = TEMPLATE_MAP[appDetail?.mode]
  if (!modeTemplates) return null
  
  const TemplateComponent = modeTemplates[locale] || modeTemplates.default
  return <TemplateComponent appDetail={appDetail} />
}, [appDetail, locale])
适用场景:深层嵌套(>3层)、复杂三元表达式,或多个
if/else
链式判断。
typescript
// ❌ 重构前:深层嵌套条件
const Template = useMemo(() => {
  if (appDetail?.mode === AppModeEnum.CHAT) {
    switch (locale) {
      case LanguagesSupported[1]:
        return <TemplateChatZh />
      case LanguagesSupported[7]:
        return <TemplateChatJa />
      default:
        return <TemplateChatEn />
    }
  }
  if (appDetail?.mode === AppModeEnum.ADVANCED_CHAT) {
    // 另外15行代码...
  }
  // 更多条件判断...
}, [appDetail, locale])

// ✅ 重构后:使用查找表+提前返回
const TEMPLATE_MAP = {
  [AppModeEnum.CHAT]: {
    [LanguagesSupported[1]]: TemplateChatZh,
    [LanguagesSupported[7]]: TemplateChatJa,
    default: TemplateChatEn,
  },
  [AppModeEnum.ADVANCED_CHAT]: {
    [LanguagesSupported[1]]: TemplateAdvancedChatZh,
    // ...
  },
}

const Template = useMemo(() => {
  const modeTemplates = TEMPLATE_MAP[appDetail?.mode]
  if (!modeTemplates) return null
  
  const TemplateComponent = modeTemplates[locale] || modeTemplates.default
  return <TemplateComponent appDetail={appDetail} />
}, [appDetail, locale])

Pattern 4: Extract API/Data Logic

模式4:提取API/数据逻辑

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.
typescript
// ❌ Before: API logic in component
const MCPServiceCard = () => {
  const [basicAppConfig, setBasicAppConfig] = useState({})
  
  useEffect(() => {
    if (isBasicApp && appId) {
      (async () => {
        const res = await fetchAppDetail({ url: '/apps', id: appId })
        setBasicAppConfig(res?.model_config || {})
      })()
    }
  }, [appId, isBasicApp])
  
  // More API-related logic...
}

// ✅ After: Extract to data hook using React Query
// use-app-config.ts
import { useQuery } from '@tanstack/react-query'
import { get } from '@/service/base'

const NAME_SPACE = 'appConfig'

export const useAppConfig = (appId: string, isBasicApp: boolean) => {
  return useQuery({
    enabled: isBasicApp && !!appId,
    queryKey: [NAME_SPACE, 'detail', appId],
    queryFn: () => get<AppDetailResponse>(`/apps/${appId}`),
    select: data => data?.model_config || {},
  })
}

// Component becomes cleaner
const MCPServiceCard = () => {
  const { data: config, isLoading } = useAppConfig(appId, isBasicApp)
  // UI only
}
React Query Best Practices in Dify:
  • Define
    NAME_SPACE
    for query key organization
  • Use
    enabled
    option for conditional fetching
  • Use
    select
    for data transformation
  • Export invalidation hooks:
    useInvalidXxx
Dify Examples:
  • web/service/use-workflow.ts
  • web/service/use-common.ts
  • web/service/knowledge/use-dataset.ts
  • web/service/knowledge/use-document.ts
适用场景:组件直接处理API调用、数据转换或复杂异步操作。
Dify 约定:使用
web/service/use-*.ts
中的
@tanstack/react-query
Hook,或创建自定义数据Hook。
typescript
// ❌ 重构前:组件内包含API逻辑
const MCPServiceCard = () => {
  const [basicAppConfig, setBasicAppConfig] = useState({})
  
  useEffect(() => {
    if (isBasicApp && appId) {
      (async () => {
        const res = await fetchAppDetail({ url: '/apps', id: appId })
        setBasicAppConfig(res?.model_config || {})
      })()
    }
  }, [appId, isBasicApp])
  
  // 更多API相关逻辑...
}

// ✅ 重构后:使用React Query提取为数据Hook
// use-app-config.ts
import { useQuery } from '@tanstack/react-query'
import { get } from '@/service/base'

const NAME_SPACE = 'appConfig'

export const useAppConfig = (appId: string, isBasicApp: boolean) => {
  return useQuery({
    enabled: isBasicApp && !!appId,
    queryKey: [NAME_SPACE, 'detail', appId],
    queryFn: () => get<AppDetailResponse>(`/apps/${appId}`),
    select: data => data?.model_config || {},
  })
}

// 组件变得更简洁
const MCPServiceCard = () => {
  const { data: config, isLoading } = useAppConfig(appId, isBasicApp)
  // 仅保留UI代码
}
Dify 中的React Query最佳实践:
  • 为查询键定义
    NAME_SPACE
    以优化组织
  • 使用
    enabled
    选项实现条件式数据获取
  • 使用
    select
    进行数据转换
  • 导出失效Hook:
    useInvalidXxx
Dify 示例:
  • web/service/use-workflow.ts
  • web/service/use-common.ts
  • web/service/knowledge/use-dataset.ts
  • web/service/knowledge/use-document.ts

Pattern 5: Extract Modal/Dialog Management

模式5:提取模态框/对话框管理逻辑

When: Component manages multiple modals with complex open/close states.
Dify Convention: Modals should be extracted with their state management.
typescript
// ❌ Before: Multiple modal states in component
const AppInfo = () => {
  const [showEditModal, setShowEditModal] = useState(false)
  const [showDuplicateModal, setShowDuplicateModal] = useState(false)
  const [showConfirmDelete, setShowConfirmDelete] = useState(false)
  const [showSwitchModal, setShowSwitchModal] = useState(false)
  const [showImportDSLModal, setShowImportDSLModal] = useState(false)
  // 5+ more modal states...
}

// ✅ After: Extract to modal management hook
type ModalType = 'edit' | 'duplicate' | 'delete' | 'switch' | 'import' | null

const useAppInfoModals = () => {
  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,
  }
}
适用场景:组件管理多个模态框,且包含复杂的显示/隐藏状态。
Dify 约定:模态框应与其状态管理逻辑一起提取。
typescript
// ❌ 重构前:组件内包含多个模态框状态
const AppInfo = () => {
  const [showEditModal, setShowEditModal] = useState(false)
  const [showDuplicateModal, setShowDuplicateModal] = useState(false)
  const [showConfirmDelete, setShowConfirmDelete] = useState(false)
  const [showSwitchModal, setShowSwitchModal] = useState(false)
  const [showImportDSLModal, setShowImportDSLModal] = useState(false)
  // 5+个其他模态框状态...
}

// ✅ 重构后:提取为模态框管理Hook
type ModalType = 'edit' | 'duplicate' | 'delete' | 'switch' | 'import' | null

const useAppInfoModals = () => {
  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

模式6:提取表单逻辑

When: Complex form validation, submission handling, or field transformation.
Dify Convention: Use
@tanstack/react-form
patterns from
web/app/components/base/form/
.
typescript
// ✅ 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>
}
适用场景:复杂表单验证、提交处理或字段转换。
Dify 约定:使用
web/app/components/base/form/
中的
@tanstack/react-form
模式。
typescript
// ✅ 使用现有表单基础设施
import { useAppForm } from '@/app/components/base/form'

const ConfigForm = () => {
  const form = useAppForm({
    defaultValues: { name: '', description: '' },
    onSubmit: handleSubmit,
  })
  
  return <form.Provider>...</form.Provider>
}

Dify-Specific Refactoring Guidelines

Dify 专属重构指南

1. Context Provider Extraction

1. Context Provider 提取

When: Component provides complex context values with multiple states.
typescript
// ❌ 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}>
  <DatasetConfigProvider value={datasetConfigValue}>
    <UIConfigProvider value={uiConfigValue}>
      {children}
    </UIConfigProvider>
  </DatasetConfigProvider>
</ModelConfigProvider>
Dify Reference:
web/context/
directory structure
适用场景:组件提供包含多个状态的复杂Context值。
typescript
// ❌ 重构前:庞大的Context值对象
const value = {
  appId, isAPIKeySet, isTrailFinished, mode, modelModeType,
  promptMode, isAdvancedMode, isAgent, isOpenAI, isFunctionCall,
  // 50+个其他属性...
}
return <ConfigContext.Provider value={value}>...</ConfigContext.Provider>

// ✅ 重构后:拆分为领域专属Context
<ModelConfigProvider value={modelConfigValue}>
  <DatasetConfigProvider value={datasetConfigValue}>
    <UIConfigProvider value={uiConfigValue}>
      {children}
    </UIConfigProvider>
  </DatasetConfigProvider>
</ModelConfigProvider>
Dify 参考
web/context/
目录结构

2. Workflow Node Components

2. 工作流节点组件

When: Refactoring workflow node components (
web/app/components/workflow/nodes/
).
Conventions:
  • Keep node logic in
    use-interactions.ts
  • Extract panel UI to separate files
  • Use
    _base
    components for common patterns
nodes/<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
适用场景:重构工作流节点组件(
web/app/components/workflow/nodes/
)。
约定:
  • 将节点逻辑放置在
    use-interactions.ts
  • 将面板UI提取到独立文件
  • 使用
    _base
    组件实现通用模式
nodes/<node-type>/
  ├── index.tsx              # 节点注册
  ├── node.tsx               # 节点可视化组件
  ├── panel.tsx              # 配置面板
  ├── use-interactions.ts    # 节点专属Hook
  └── types.ts               # 类型定义

3. Configuration Components

3. 配置组件

When: Refactoring app configuration components.
Conventions:
  • Separate config sections into subdirectories
  • Use existing patterns from
    web/app/components/app/configuration/
  • Keep feature toggles in dedicated components
适用场景:重构应用配置组件。
约定:
  • 将配置区块拆分为子目录
  • 遵循
    web/app/components/app/configuration/
    中的现有模式
  • 将功能开关放置在专属组件中

4. Tool/Plugin Components

4. 工具/插件组件

When: Refactoring tool-related components (
web/app/components/tools/
).
Conventions:
  • Follow existing modal patterns
  • Use service hooks from
    web/service/use-tools.ts
  • Keep provider-specific logic isolated
适用场景:重构工具相关组件(
web/app/components/tools/
)。
约定:
  • 遵循现有模态框模式
  • 使用
    web/service/use-tools.ts
    中的服务Hook
  • 隔离供应商专属逻辑

Refactoring Workflow

重构工作流

Step 1: Generate Refactoring Prompt

步骤1:生成重构提示

bash
pnpm refactor-component <path>
This command will:
  • Analyze component complexity and features
  • Identify specific refactoring actions needed
  • Generate a prompt for AI assistant (auto-copied to clipboard on macOS)
  • Provide detailed requirements based on detected patterns
bash
pnpm refactor-component <path>
该命令将:
  • 分析组件复杂度和功能
  • 识别需要执行的具体重构操作
  • 生成AI助手提示(在macOS上自动复制到剪贴板)
  • 根据检测到的模式提供详细要求

Step 2: Analyze Details

步骤2:分析细节

bash
pnpm analyze-component <path> --json
Identify:
  • Total complexity score
  • Max function complexity
  • Line count
  • Features detected (state, effects, API, etc.)
bash
pnpm analyze-component <path> --json
识别以下内容:
  • 总复杂度分数
  • 单个函数的最高复杂度
  • 代码行数
  • 检测到的功能(状态、副作用、API等)

Step 3: Plan

步骤3:制定计划

Create a refactoring plan based on detected features:
Detected FeatureRefactoring 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
根据检测到的功能制定重构计划:
检测到的功能重构操作
hasState: true
+
hasEffects: true
提取自定义Hook
hasAPI: true
提取数据/服务Hook
hasEvents: true
(数量多)
提取事件处理器
lineCount > 300
拆分为子组件
maxComplexity > 50
简化条件逻辑

Step 4: Execute Incrementally

步骤4:增量执行

  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: 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       │
  └────────────────────────────────────────┘
  1. 每次只提取一部分代码
  2. 每次提取后运行lint、类型检查和测试
  3. 验证功能正常后再进行下一步
对于每一次提取:
  ┌────────────────────────────────────────┐
  │ 1. 提取代码                            │
  │ 2. 执行:pnpm lint:fix                  │
  │ 3. 执行:pnpm type-check:tsgo           │
  │ 4. 执行:pnpm test                      │
  │ 5. 手动测试功能                        │
  │ 6. 通过?→ 进行下一次提取             │
  │    失败?→ 修复后再继续               │
  └────────────────────────────────────────┘

Step 5: Verify

步骤5:验证

After refactoring:
bash
undefined
重构完成后:
bash
undefined

Re-run refactor command to verify improvements

重新运行重构命令验证改进效果

pnpm refactor-component <path>
pnpm refactor-component <path>

If complexity < 25 and lines < 200, you'll see:

如果复杂度<25且代码行数<200,你将看到:

✅ COMPONENT IS WELL-STRUCTURED

✅ COMPONENT IS WELL-STRUCTURED

For detailed metrics:

查看详细指标:

pnpm analyze-component <path> --json
pnpm analyze-component <path> --json

Target metrics:

目标指标:

- complexity < 50

- complexity < 50

- lineCount < 300

- lineCount < 300

- maxComplexity < 30

- maxComplexity < 30

undefined
undefined

Common Mistakes to Avoid

需避免的常见错误

❌ Over-Engineering

❌ 过度设计

typescript
// ❌ 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 }
}
typescript
// ❌ 过多微小的Hook
const useButtonText = () => useState('Click')
const useButtonDisabled = () => useState(false)
const useButtonLoading = () => useState(false)

// ✅ 内聚的Hook,包含相关状态
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
  • Maintain naming conventions
  • Preserve export patterns for compatibility
  • 遵循现有目录结构
  • 保持命名约定
  • 保留导出模式以确保兼容性

❌ Premature Abstraction

❌ 过早抽象

  • Only extract when there's clear complexity benefit
  • Don't create abstractions for single-use code
  • Keep refactored code in the same domain area
  • 仅当能明确降低复杂度时才进行提取
  • 不为仅使用一次的代码创建抽象
  • 保持重构后的代码在同一领域范围内

References

参考资料

Dify Codebase Examples

Dify 代码库示例

  • Hook extraction:
    web/app/components/app/configuration/hooks/
  • Component splitting:
    web/app/components/app/configuration/
  • Service hooks:
    web/service/use-*.ts
  • Workflow patterns:
    web/app/components/workflow/hooks/
  • Form patterns:
    web/app/components/base/form/
  • Hook 提取
    web/app/components/app/configuration/hooks/
  • 组件拆分
    web/app/components/app/configuration/
  • 服务Hook
    web/service/use-*.ts
  • 工作流模式
    web/app/components/workflow/hooks/
  • 表单模式
    web/app/components/base/form/

Related Skills

相关技能

  • frontend-testing
    - For testing refactored components
  • web/docs/test.md
    - Testing specification
  • frontend-testing
    - 用于测试重构后的组件
  • web/docs/test.md
    - 测试规范