ref
React提供的这个ref
属性,表示为对组件真正实例的引用,其实就是ReactDOM.render()
返回的组件实例,ref
可以挂载到组件上也可以是dom元素上。
- 挂到组件(
class
声明的组件)上的ref表示对组件实例的引用。不能在函数式组件上使用 ref 属性,因为它们没有实例(react 16.8新增Hooks useRef可以在函数式组件上使用ref属性)。 - 挂载到dom元素上时表示具体的dom元素节点。
在React 最新的版本中,要使用ref
, 需要使用React.createRef
方法先生成一个ref
。
import React, { Component, createRef } from 'react'
import ReactDOM from 'react-dom'
class App extends Component {
constructor() {
super()
// 创建inputRef
this.inputRef = createRef()
}
componentDidMount () {
console.log(this.inputRef.current) // <input type="text">
}
render () {
return (
<div>
{/* 关联ref和dom */}
<input type="text" ref={this.inputRef} />
</div>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('root')
)
函数式组件中,使用useRef来获取到真实的Dom
import React, { useRef } from 'react'
export default function App(){
const inputRef = useRef(null)
const onButtonClick = () => {
// `current` 指向已挂载到 DOM 上的文本输入元素
console.log(inputRef.current) // <input type="text">
inputRef.current.focus()
}
return (
<>
<input ref={inputRef} type="text" />
<button onClick={onButtonClick}>Focus the input</button>
</>
)
}
在useRef
创建的ref仿佛就像外部定义的一个全局变量,不会随着组件的更新而重新创建。但组件销毁,它也会消失,不用手动进行销毁。故而可以使用useRef来存储常量:
import React, { useState, useEffect, useRef } from 'react'
export default function App(props){
const [count, setCount] = useState(0)
// 通过useRef来存储timerID,这样便可以在多次渲染之后依旧保存定时器ID
const timerID = useRef()
useEffect(() => {
timerID.current = setInterval(()=>{
setCount(count => count + 1)
}, 1000)
}, [])
useEffect(()=>{
if(count > 10){
// 定时器ID保持不变,从而能正常清除定时器。
clearInterval(timerID.current)
}
})
return (
<>
<button onClick={() => {setCount(count + 1)}}>Count: {count}</button>
</>
)
}