✅ Tailwind CSS+Reactの複数チェックボックス
2020-11-08
/Development
この記事は最終更新日から2年以上経過しています。
昨日 に続いて Tailwind CSS のカスタムフォームも触ってみました。カスタムフォームのCSSは別途プラグインを入れる必要があるんですね。 あとついでにReactで複数チェックボックスを扱う方法も調べてみてたんですが色々出てきて都度迷ってしまいそうなのでメモ。
インストール
コピーしました
$ yarn add @tailwindcss/custom-forms -D
プラグインを追加
コピーしました
// tailwind.config.js
module.exports = {
// ...
plugins: [require("@tailwindcss/custom-forms")],
};
コンポーネント側
コピーしました
import React, { useEffect, useState } from "react";
const CheckBox = (props) => {
return (
<>
<input type="checkbox" className="form-checkbox" type="checkbox" id={props.name} name={props.name} checked={props.checked} onChange={props.onChange} value={props.value} />
<label className="ml-2 text-sm" htmlFor={props.name}>
{props.label}
</label>
</>
);
};
const CheckBoxes = (props) => {
const [checkedItems, setCheckedItems] = useState(props.checkedItems || []);
const checkboxes = props.checkboxes || [
{
name: "checkbox_0",
label: "item0",
value: "0",
},
];
useEffect(() => {
if (props.onUpdate) props.onUpdate({ checkedItems: checkedItems });
}, [checkedItems]);
const onChange = (e) => {
if (e.target.checked) {
setCheckedItems([...checkedItems, e.target.value]);
} else {
setCheckedItems(checkedItems.filter((i) => i !== e.target.value));
}
};
const onReset = (e) => {
setCheckedItems([]);
};
return (
<>
<fieldset className="my-2">
<legend className="text-sm text-gray-700 mb-2">{props.legend || "Checkboxes"}</legend>
{checkboxes.map((item) => {
return (
<div key={item.name} className="block items-center py-1">
<CheckBox {...item} checked={checkedItems.includes(item.value)} onChange={onChange} />
</div>
);
})}
<div className="text-right">
<button type="button" className="text-sm text-gray-500" onClick={onReset}>
Reset
</button>
</div>
</fieldset>
</>
);
};
export default CheckBoxes;
使う側
使い回ししたいので、onUpdate
含めコンポーネントの中身は触らないで良いようにしておきました。
コピーしました
<CheckBoxes
{...{
onUpdate: onUpdateCheckboxes,
legend: "Checkboxes",
checkedItems: ["0", "1", "2"],
checkboxes: [
{
name: "checkbox_0",
label: "Item0",
value: "0",
},
{
name: "checkbox_1",
label: "Item1",
value: "1",
},
{
name: "checkbox_2",
label: "Item2",
value: "2",
},
],
}}
/>
所感
ReactではVueのv-model
的なものが無いので自前でなんとかしなければならなくてどう実装したらよいのか迷ったのですが、ちょっと調べてみたところ色々なやり方が出てきて悩ましいですね…
連想配列のcheckedItems
にスプレッド構文を使ってChangeイベントがあったものを { name: checked }
みたいな感じで追加していく方法が比較的多くヒットしたのですが、これだと格納されているものには非アクティブなものが含まれているし全てのチェックボックスを触るまで抜けがある状態になってしまってなんだか違和感があるのでcheckedItems
を配列にして追加or削除をするようにしてみました。
APIに値を送信するような用途で使う時はアクティブなvalueだけが入った配列があると嬉しいので。
Comment
comments powered by Disqus