{"record":{"id":"7057232ced7cb595","repo":"oxc-project/oxc","slug":"use-either-checked-or-defaultchecked-but-not","errorCode":null,"errorMessage":"Use either `checked` or `defaultChecked`, but not both.","messagePattern":"Use either `checked` or `defaultChecked`, but not both\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/react/checked_requires_onchange_or_readonly.rs","lineNumber":25,"sourceCode":"use oxc_span::Span;\nuse schemars::JsonSchema;\nuse serde::Deserialize;\n\nuse crate::{\n    AstNode,\n    context::LintContext,\n    rule::{DefaultRuleConfig, Rule},\n    utils::{get_element_type, get_jsx_attribute_name, is_create_element_call},\n};\n\nfn missing_property(span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"`checked` should be used with either `onChange` or `readOnly`.\")\n        .with_help(\"Add either `onChange` or `readOnly`.\")\n        .with_label(span)\n}\n\nfn exclusive_checked_attribute(checked_span: Span, default_checked_span: Span) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Use either `checked` or `defaultChecked`, but not both.\")\n        .with_help(\"Remove either `checked` or `defaultChecked`.\")\n        .with_labels([checked_span, default_checked_span])\n}\n\n#[derive(Debug, Default, Clone, JsonSchema, Deserialize)]\n#[serde(rename_all = \"camelCase\", default, deny_unknown_fields)]\npub struct CheckedRequiresOnchangeOrReadonly {\n    /// Ignore the requirement to provide either `onChange` or `readOnly` when the `checked` prop is present.\n    ignore_missing_properties: bool,\n    /// Ignore the restriction that `checked` and `defaultChecked` should not be used together.\n    ignore_exclusive_checked_attribute: bool,\n}\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// This rule enforces `onChange` or `readOnly` attribute for checked property of input elements.\n    /// It also warns when `checked` and `defaultChecked` properties are used together.","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/react/checked_requires_onchange_or_readonly.rs#L7-L43","documentation":"Diagnostic from the oxlint rule `react/checked-requires-onchange-or-readonly` (plugin `react`, category `pedantic`). It fires when an `<input>` carries BOTH `checked` and `defaultChecked` attributes. The two are the controlled and uncontrolled ways to set checked state and are mutually exclusive; React ignores one of them and the component's behavior becomes unpredictable across renders. The diagnostic carries two labels - one on each attribute span - and the `ignoreExclusiveCheckedAttribute` option disables the check.","triggerScenarios":"`<input type=\"checkbox\" checked defaultChecked />`; `<input type=\"radio\" checked={a} defaultChecked={b} />`; `createElement('input', { checked: true, defaultChecked: true })`.","commonSituations":"Merge of a default-initialization prop with a controlled prop; copy-paste between controlled and uncontrolled components; wrapper components forwarding both props to the inner input.","solutions":["Keep `checked` (controlled) and delete `defaultChecked`","Keep `defaultChecked` (uncontrolled initial value) and delete `checked`","If a wrapper may receive both, filter one out before spreading onto the input"],"exampleFix":"// before\n<input type=\"checkbox\" checked={done} defaultChecked={false} onChange={toggleDone} />\n\n// after\n<input type=\"checkbox\" checked={done} onChange={toggleDone} />","handlingStrategy":"validation","validationCode":"npx oxlint --react/checked-requires-onchange-or-readonly src/","typeGuard":"// Guard for wrapper components before spreading props:\nconst hasExclusiveCheckedConflict = (p: {\n  checked?: unknown;\n  defaultChecked?: unknown;\n}): boolean => 'checked' in p && 'defaultChecked' in p;","tryCatchPattern":null,"preventionTips":["Choose controlled (`checked`) or uncontrolled (`defaultChecked`) per component - never both","In wrappers that forward props, strip one of the two before spreading onto `<input>`","React's docs treat these as mutually exclusive; follow the same rule in prop types (omit one)"],"tags":["react","jsx","lint","controlled-components","forms","oxlint"],"backgroundTag":"mutually-exclusive-react-props","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}