React checkbox の checked と defaultChecked
React で checkbox の状態を別のところにある label で制御していて warning が出ていた
const Component = () => { const [isActive, setIsActive] = useState<boolean>(true); const handleOnActive = () => setIsActive(true); const handleDeActive = () => setIsActive(false); return ( <div> <input id="myCheckbox" type="checkbox" checked={isActive} /> <div className="tab"> <label htmlFor="myCheckbox" onClick={handleOnActive}>Tab 1</label> <label htmlFor="myCheckbox" onClick={handleDeActive}>Tab 2</label> </div> <div className="tabContent"> <div className={`content1 ${isActive ? 'show' : 'hide'}`} aria-hidden={!isActive}>content 1</div> <div className={`content2 ${isActive ? 'hide' : 'show'}`} aria-hidden={isActive}>content 2</div> </div> </div> ); };
You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.
環境
- React
18.2.0 - TypeScript
5.2.2
Controlled Component には onChange か readOnly が必要
value や checked という状態を state 制御している Controlled Components は直接 state を変更できる onChange を付けるか別のところで state を変更する場合は readOnly にしておく必要がある
今回のケースだと label のクリックで checkbox の cheked (状態) を変更したいので readOnly を付ける必要があった
const Component = () => {
const [isActive, setIsActive] = useState<boolean>(true);
const handleOnActive = () => setIsActive(true);
const handleDeActive = () => setIsActive(false);
return (
<div>
- <input id="myCheckbox" type="checkbox" checked={isActive} />
+ <input id="myCheckbox" type="checkbox" checked={isActive} readOnly />
<div className="tab">
<label htmlFor="myCheckbox" onClick={handleOnActive}>Tab 1</label>
<label htmlFor="myCheckbox" onClick={handleDeActive}>Tab 2</label>
</div>
{/* 略 */}
</div>
);
};
Checkbox / Radio の checked と defaultChecked
- checkbox / radio のチェック状態は
valueではなくcheckedで管理する。(デフォルト値はdefaultValueでなくdefaultCheckedを使う) checkedとdefaultCheckedは同時には使えない- 同時に使用すると warning が発生する
Component contains an input of type checkbox with both checked and defaultChecked props. Input elements must be either controlled or uncontrolled (specify either the checked prop, or the defaultChecked prop, but not both). Decide between using a controlled or uncontrolled input element and remove one of these props.
checkedがある場合はチェックの状態は state で制御されるのでデフォルト値を設定する必要がない- チェック状態を state で制御しない 非制御コンポーネント (
Uncontrolled Components) として扱う場合はdefaultCheckedのみを使う
- 同時に使用すると warning が発生する
先のコンポーネントの check 状態を通常の HTML のように for を使った label で変更させるだけであれば defaultChecked を使った非制御コンポーネントにすることもできる
const UnControlledComponent = () => { return ( <div> <input id="myCheckbox" type="checkbox" defaultChecked={true} /> <div className="tab"> <label htmlFor="myCheckbox">Tab 1</label> <label htmlFor="myCheckbox">Tab 2</label> </div> <div className="tabContent"> {/* state を使わないので表示の切り替えは CSS で行う */} <div className="content1">content 1</div> <div className="content2">content 2</div> </div> </div> ); };
まとめ
- Radiobox / Radio のコンポーネントで state を使う必要があるのかどうかで Controlled Components にするか Uncontrolled Components を決める
- Uncontrolled Components なら
defaultCheckedを使う - Controlled Components なら
checkedで状態を state で扱う- 直接変更するには
onClickを渡して state を変更できるようにする - label など別の要素から state を変更する場合は Checkbox / Radio には
readOnlyを付ける
- 直接変更するには
[参考]

