Checkboxのコンポーネントを作るになんでこれだけのコード量が必要になるのだろうか... Hooksもふんだんに使われている。
import React, { useCallback, useEffect, useRef, useState } from "react"; import styled from "styled-components"; import { CheckBoxIcon, CheckBoxOutlineBlankIcon, } from "components/atoms/IconButton"; import Text from "components/atoms/Text"; import Flex from "components/layout/Flex"; export interface CheckBoxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "defaultValue"> { /** * 表示ラベル */ label?: string; } const CheckBoxElement = styled.input` display: none; `; const Label = styled.label` cursor: pointer; margin-left: 6px; user-select: none; `; /** * チェックボックス */ const CheckBox = (props: CheckBoxProps) => { const { id, label, onChange, checked, ...rest } = props; const [isChecked, setIsChecked] = useState(checked); const ref = useRef<HTMLInputElement>(null); const onClick = useCallback( (e: React.MouseEvent) => { e.preventDefault(); // チェックボックスを強制的にクリック ref.current?.click(); setIsChecked((isChecked) => !isChecked); }, [ref, setIsChecked] ); useEffect(() => { // パラメータからの変更を受け付ける setIsChecked(checked ?? false); }, [checked]); return ( <> <CheckBoxElement {...rest} ref={ref} type="checkbox" checked={isChecked} readOnly={!onChange} onChange={onChange} /> <Flex alignItems="center"> {/* チェックボックスのON/OFFの描画 */} {checked ?? isChecked ? ( <CheckBoxIcon size={20} onClick={onClick} /> ) : ( <CheckBoxOutlineBlankIcon size={20} onClick={onClick} /> )} {/* チェックボックスのラベル */} {label && label.length > 0 && ( <Label htmlFor={id} onClick={onClick}> <Text>{label}</Text> </Label> )} </Flex> </> ); }; export default CheckBox;
個人的にはこれぐらいでよいのではと感じる。propでUIコンポーネントが受け取るパラメータをtypeで定義して代入する。場合によっては、useEffectやuseStateをonChangeに仕込むなりしたらいい。
type Props = { //idを追加 id: string; value: boolean; text: string; onChange: () => void; }; export const Checkbox = ({ id, value, text, onChange }: Props) => { return ( <div> <label htmlFor={id}> <div> <input type="checkbox" id={id} checked={value} onChange={() => { onChange(); }} /> </div> <div> {text} </div> </label> </div> ); };