react useRef和createRef

512 阅读2分钟

首先说一下为什么要使用useRef和createRef:

useRef和createRef可以存放任何东西,最常见的用法就是操作DOM(如在input上放ref,可直接操作input),还有就是当作定义的一个跨越渲染不受渲染影响的变量。

操作DOM好理解就是可以不使用原声js来操作DOM了, 更方便了

export default () => {
    const inputRef = useRef()    
    return (        
        <div>            
            <input type="text" ref={inputRef} />            
            <button onClick={() => {inputRef.current.onFocus()}}>聚焦</button>
            <div>input的值{inputRef.current.getValue()}</div>
        </div>    
    )
}

定义跨渲染的变量:

export default () => {    
    const [value, setValue] = useState(1)    
    return (
        <div>
            <p>value的值:{value}</p>
            <button onClick={() => {setValue(value+1)}}>按我+1哦</button>
            <button onClick={() => {
                setTimeout(() => {
                    alert(value)
                }, 3000)
            }}>点我弹窗</button>
        </div>
    )
}

上图中代码当你点击弹窗按钮,然后立马在点击“+1按钮”, 结果会怎样呢? 

页面上的value值会显示2,3s后会弹窗显示值1

为什么会发生这样的情况呢?

因为每次使用react使用setState的时候都会触发渲染函数,把把函数组建重新执行一下, 那有人会问问什么重新执行,state没有保持原来的数据而是使用了最新的数据,个人认为可以理解成, 函数组建每次的渲染都会保留一份属于自己的数据,会通过state会通过setState把最新的state传给组件,然后组件渲染DOM, 每一次渲染都属保留自己的那一份state值。

如何理解保留本次渲染的state值呢?

如上图代码先点击弹窗按钮,执行到setTimeout异步函数, 需要使用的value值是本次渲染的1,点击完弹窗按钮,立刻点击+1按钮, 此时弹窗还没出现,而setState已经出发value值+1,并重新渲染,所以页面上显示的value值是2,而弹窗里显示的值虽然是后出现的, 但是它使用的依然是上一次渲染的value值1.

useRef和createRef的区别:

useRef在函数组建中使用, createRef在类组建中使用,createRef在函数组建中使用会失去它的意义, 它会随着组建重新执行而被重新赋值,createRef 每次渲染都会返回一个新的引用,而 useRef 每次都会返回相同的引用

export default () => {
    const [val, setVal] = useState(1)
    const uRef = useRef()
    const cRef = React.createRef()
    if (!uRef.current) {
        uRef.current = val
    }
    if (!cRef.current) {
        cRef.current = val
    }
    return (
        <div>
            <p onClick={() => {setVal(val+1)}}>+1</p>
            <p>val: {val}</p>
            <p>uRef: {uRef.current}</p>
            <p>cRef: {cRef.current}</p>
        </div>
    )
}

如上图结果所示,每次函数组建被执行,createRef也被初始化了