LoginSignup
0
0

More than 3 years have passed since last update.

【React】動的に用意したイベントハンドラのindexを取得する

Last updated at Posted at 2020-02-18

2020/2/20追記

indexを引数で渡せないわけないよなと思いながらこの記事書いてたけど,やっと渡し方わかった笑

.js
handleChange_todohuken = (e, index) => {)

<Autocomplete
  onChange={e => this.handleChange_todohuken(e, input)}
>

終わり笑

困った状況

今回はFormを登録したい数だけ動的に用意することを考えた.reactでの実装なので,Fromで入力された値はstateに持たせたい.この時に考えないといけないことは,動的に用意したどこのstateが変更されたのかを判定するためにそのFormが何番目のものであるかのindexを取得したいこと.
スクリーンショット 2020-02-18 23.41.03.png

解決法

コンポーネントのidにindex番号を入れておいてあとで取り出す.

.js
handleChange_concert = e => {
  const index = e.target.id.split(' ')[0].replace('index', '');

  // stateの配列を更新するためコピー先の配列全体を変更する
  const concerts_copy = this.state.concerts.slice();
  concerts_copy[index] = e.target.value;
  this.setState({ concerts: concerts_copy });
}

{this.state.inputs.map(input =>
  <div key={input}>
    <TextField
      label="ライブ名"
      id={`index${input} standard-basic`}
      onChange={this.handleChange_concert}
      value={this.state.concerts[input]}
      required
    />
  </div>
)}

MaterialUIのAutocompleteの余談

ここでstate.todohukensの配列に都道府県名を格納することにかなり悩んで時間かかった.  
最初はAutocompleteの中のTextFieldにonChangeを持たせていたが,当然のことながら格納されるのはoptionsから選んだ都道府県名ではなく,キーボード入力された値のみ.
AutocompleteにonChangeを持たせることでoptionsから値が選ばれた時にコールバック関数が動くので正常に値がとれる.

.js
<Autocomplete
  id={`index${input} combo-box-demo`}
  options={options}
  getOptionLabel={option => option.label}
  onChange={this.handleChange_todohuken}
  style={{ width: 300 }}
  renderInput={params => (
    <TextField {...params}
      label="都道府県"
      id="standard-basic"
      required
      fullWidth
    />
  )}
/>

あとAutocompleteには選んだ都道府県名を空文字に戻せるxボタンがテキストフィールド右側に配置されてるが,今回上のindexのとりかたをする時にe.targetを使っているためクリックする要素が変わるとindexの取り方も変えないといけなかった.やり方が全然スマートでない...
この辺,reactでどうやってきれいに書いたらいいのかまだ分かりません,教えてください〜

.js
handleChange_todohuken = e => {
  // 都道府県プルダウン操作した時
  let index;
  if (e.target.id){
    index = e.target.id.split(' ')[0].replace('index', '');
  }
  // 右のxボタンで都道府県名を消した場合
  else{
    index = e.target.parentElement.parentElement.parentElement.parentElement.querySelector('input').id.split(' ')[0].replace('index', '');
  }
  const str = e.target.innerHTML[0] == '<' ? '' : e.target.innerHTML;

  // stateの配列を更新するためコピー先の配列全体を変更する
  const todohukens_copy = this.state.todohukens.slice();
  todohukens_copy[index] = str;
  this.setState({ todohukens: todohukens_copy });
}
0
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
0
0