LoginSignup
1
0

More than 3 years have passed since last update.

React(TypeScript)のlabelタグにnameやvalue属性の代替え属性をいれる

Last updated at Posted at 2021-01-15

結論としてカスタム属性を使います。

JSX上でinputタグ(type="radio")とlabelの擬似要素を組み合わせた際に実際にクリックされる方であるlabelタグの属性にnameやvalueを使えずつまづいたので代替え方法のTIPSです。

背景

ご存知のようにinput + labelのスタイル制御はJSを使わずに選択されたラベルのスタイルを変更するHTML/CSSでこれまで使われきた手法です。

わざわざReactでこのテクニックを使ってしまったところlabelクリック時に状態を保存したいのですがlabelタグにnameやvalueといった属性は使えないためlabeタグに必要な情報を埋め込めなくなりました。

素直にJSオンリーでスタイル制御すべきだった...
nameやvalueをlabelタグへそのまま使うと当然のようにそんな属性の型はねえぞと怒られる。

Type '{ children: string; onClick: (e: MouseEvent<HTMLLabelElement, MouseEvent>) => void; value: string | number; id: string; htmlFor: string; }' is not assignable to type 'DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>'.
  Property 'value' does not exist on type 'DetailedHTMLProps<LabelHTMLAttributes<HTMLLabelElement>, HTMLLabelElement>'.ts(2322)

もうCSSでスタイルを当ててしまったあとだし作り変えるための優先順位はそこまで高くないしということでこのままlabelで使えるようにしました。同じような人はどうぞ。

解決策:カスタム属性を使う

といっても解決策は単純でnameやvalueに変わる属性を付与します。

<label data-{任意の名前} >Hello 沼!</label>

というようにカスタム属性を使います。

sample.tsx
<label onClick={e => handleClickChange(e)} data-name={name} data-value={value} 
 htmlFor={idName} >Hello !</label>

引っ張る際には e.currentTarget.dataset.{任意のカスタムデータ名} で引っ張れます。接頭辞のdata-は不要ですが。
そしてTypeScriptとしてアサーションを使うのは御行儀がよくないのですが下のような形で引っ張ってこれました。

sample.tsx
  const handleClickChange = (e: MouseEvent): void => { 
    const name = (e.currentTarget as HTMLInputElement).dataset.name as string;
    const value = (e.currentTarget as HTMLInputElement).dataset.value;
    setProfile(currentValue => ({
      ...currentValue,
      [name]: value
    }));
  }

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0