[PR #32399] refactor(web): make Switch controlled-only and migrate call sites #33713

Closed
opened 2026-02-21 20:53:45 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/langgenius/dify/pull/32399

State: closed
Merged: Yes


Background

This PR refactors the base Switch component to a controlled-only API and migrates existing usages to match that contract.

Problem

  • Switch previously supported both controlled (value) and uncontrolled (defaultValue + internal state) modes.
  • Dual ownership makes state flow ambiguous and can introduce sync issues and effect-driven workarounds.
  • The API was harder to reason about at call sites because both patterns coexisted.

Decision

  • Make Switch controlled-only with value: boolean as the single source of truth.
  • Remove uncontrolled behavior and internal useState from the component.
  • Keep onChange optional so read-only and disabled usage remains ergonomic.
  • Migrate all affected call sites from defaultValue to value.

Model

  • Data model: parent owns state (value) and passes it down.
  • Interaction model: Switch computes nextChecked on interaction and emits onChange(nextChecked).
  • Ownership model: no internal value ownership in Switch, avoiding controlled/uncontrolled mixing.

Impact

  • Predictable, explicit state ownership across the UI.
  • Removes a common React anti-pattern source (mixed controlled/uncontrolled state).
  • Cleaner component contract and easier testability and maintenance.
  • Updated stories/specs and call sites to reflect the new API.

Validation

  • Ran pnpm eslint --cache --concurrency=auto --prune-suppressions on the 57 touched files only, without --fix.
  • Result: 0 errors, warnings only, and no new working tree changes.
**Original Pull Request:** https://github.com/langgenius/dify/pull/32399 **State:** closed **Merged:** Yes --- ## Background This PR refactors the base `Switch` component to a controlled-only API and migrates existing usages to match that contract. ## Problem - `Switch` previously supported both controlled (`value`) and uncontrolled (`defaultValue` + internal state) modes. - Dual ownership makes state flow ambiguous and can introduce sync issues and effect-driven workarounds. - The API was harder to reason about at call sites because both patterns coexisted. ## Decision - Make `Switch` controlled-only with `value: boolean` as the single source of truth. - Remove uncontrolled behavior and internal `useState` from the component. - Keep `onChange` optional so read-only and disabled usage remains ergonomic. - Migrate all affected call sites from `defaultValue` to `value`. ## Model - Data model: parent owns state (`value`) and passes it down. - Interaction model: `Switch` computes `nextChecked` on interaction and emits `onChange(nextChecked)`. - Ownership model: no internal value ownership in `Switch`, avoiding controlled/uncontrolled mixing. ## Impact - Predictable, explicit state ownership across the UI. - Removes a common React anti-pattern source (mixed controlled/uncontrolled state). - Cleaner component contract and easier testability and maintenance. - Updated stories/specs and call sites to reflect the new API. ## Validation - Ran `pnpm eslint --cache --concurrency=auto --prune-suppressions` on the 57 touched files only, without `--fix`. - Result: `0 errors`, warnings only, and no new working tree changes.
yindo added the pull-request label 2026-02-21 20:53:45 -05:00
yindo closed this issue 2026-02-21 20:53:45 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#33713