React で <select> を使いたいけどちょっと困った話

constructor

this.state({value: ''});

としておいて、 render

render () {
  const hoge = [{name: 'test'}]; // セレクトボックスの選択候補となる要素。実際には Redux で管理していて store.getState().hoge みたいにしてとってくることを想定。状況によって値が変わる
  
  const options = hoge.map(e => {
    return <option value={e.name} key={e.name}>{e.name}</option>;  
  });

  return (
    <select value={this.state.value} size="3" onChange={this.handleChange}>
      {options}
    </select>
  );
}

みたいにすると、初期状態で「test」という選択肢だけが存在するセレクトボックスが表示されますが、この「test」をクリックしても onChange が発火しません。

this.state.value が空文字列のまんま更新されず、困っておりました。

React の公式ドキュメントの <select> の項目 Forms - React を見ると、

this.state = {value: 'coconut'};

と初期値を constructor 内で設定していますが、自分の例で言うところの options はその時々で中身が変わるため、初期値をハードコードすることもできない状況です。

対処法がないものかと考えて、componentWillReceiveProps を使って this.state.valueoptions の先頭要素を突っ込んでしまうというのを思いつきました。

componentWillReceiveProps() {
  const { hoge } = store.getState(); // hoge には [{name: 'test'}] が入ると想定
  if (hoge.length > 0) {
    this.setState({
      value: hoge[0].name,
    });
  }
}

みたいな感じです。こうすればレンダリングされるときには this.state.valuehoge.name が入っているので、submit するなりなんなりできます。

もっと賢い解決方法があったら知りたいですが、とりあえずこれで所望の挙動は得られました。