idとrefって実質的に同じだから、それならidでいいじゃんという話を前に同僚としていたのですが、色々使っててやっぱりrefの方がいいなと思ったのでポイントをまとめます。
名前の影響範囲を限定できる
idってHTML文書内で一意になる必要があるわけです。Componentの呼び出し階層の下の方でidを定義した場合、同じ名前を他で使ってるかどうかわからなくなりますね。実質的に問題がなくても、可能性があるだけで落ち着かない。(なので自分はそもそもid属性を極力避ける)
その点、refであればそのComponentの中だけの事なので、影響を気にせず使えるわけです。
コードなので表現力がある
繰り返し属性に対してidを振るような場合、以下みたいな感じになるかと思います。
list.map((n,i) => (
<input id={`list[${i}].name`} type='text' defaultValue={n.name} onChange={e => this.doSomething(e,i)} />
))
Template literal 合ってたかなって毎回調べますね。今も調べた。言語をまたぐとやんなっちゃいますね。使うときもdocument.getElementById(`list[${i}].name`)
とかせにゃならん。
refならこう
list.map((n,i) => (
<input ref={r => {
this.list = this.list || []
this.list[i] = {name: r}
}} type='text' defaultValue={n.name} onChange={e => this.doSomething(e,i)} />
))
めんどくさかったので冗長になりましたが、list
の初期化とかはコンストラクタでやればいいです。これでthis.list[i].name
で参照できる。
以上より、refを積極的に使いたいと思う次第です。