以前我們要抓一個DOM的時候很習慣用document.getElementById、document.getElementsByClassName等等的語法來取得我們要的 DOM元素,但假設在react中要取得 DOM可以怎麼做?就可以利用React.createRef(),這是react v16.3開始用的語法,更舊的版本是採用CallBack Ref的方法。
React官網也提到不要過度使用Ref ,應該先思考是否能單純用state來解決問題,因為當專案越來越複雜,理想狀況是用State和Props控管組件,但如果使用了很多Ref,在管理 DOM上就會變得不好維護,像是一個簡單的彈窗,開關的方法應該由父組件透過props傳給子組件,而不是用Ref來控制component
在createRef()的instance創建出來時,就會同時被紀錄在組件的變數上(myRef),並且將需要被參考的對象指定Ref屬性,如此一來就可以在整個component裡被取得。
import React, { Component, Fragment, createRef } from 'react';
class RefExample extends Component{
constructor(){
super()
this.myRef = createRef()
}
getText = () =>{
console.log(this.myRef.current.innerText)
}
render(){
return(
<Fragment>
<div ref={this.myRef}>test</div>
<button onClick={this.getText}>click</button>
</Fragment>
)
}
}
console.log(this.myRef),會發現myRef底下還多一層current,因此我們要取得DOM就要透過this.myRef.current
可以看到Ref屬性代入的是一個callback function,將自身的html tag傳入,並讓myRef這個變數指向當前這個div
要注意的是不能在function component上使用Ref ,因為他們沒有instance
class RefExample extends Component {
constructor() {
super()
}
getText = () => {
console.log(this.myRef.innerText)
}
render() {
return (
<Fragment>
<div ref={(div)=>{
this.myRef = div
}}>test</div>
<button onClick={this.getText}>click</button>
</Fragment>
)
}
}
React component也可以用Ref
class RefExample extends Component {
constructor() {
super()
this.listRef = createRef()
}
componentDidMount() {
this.listRef.current.showList()
}
render() {
return (
<Fragment>
<List ref={this.listRef} />
</Fragment>
)
}
}