react中的useRef

前言

react hooks 是 React 16.8 的新增特性。 它可以让我们在函数组件中使用 state 、生命周期以及其他
react特性,而不仅限于 class 组件。react hooks 的出现,标示着
react中不会在存在无状态组件了,只有类组件和函数组件。具体可查看官网。

优势:

函数组件不能使用state,遇到交互更改状态等复杂逻辑时不能更好地支持,hooks让函数组件更靠近class组件,拥抱函数式编程。
解决副作⽤问题,hooks出现可以处理数据获取、订阅、定时执行任务、手动修改
ReactDOM这些⾏为副作用,进行副作用逻辑。比如useEffect。 更好写出有状态的逻辑重用组件。
让复杂逻辑简单化,比如状态管理:useReducer、useContext。
函数式组件比class组件简洁,开发的体验更好,效率更⾼,性能更好。 更容易发现无用的状态和函数。

useRef介绍

const refContainer = useRef(initialValue);

1

useRef 返回一个可变的 ref 对象,其 .current 属性被初始化为传入的参数(initialValue)。返回的 ref
对象在组件的整个生命周期内保持不变。

本质上,useRef 就像是可以在其 .current 属性中保存一个可变值的“盒子”。

然而,useRef() 比 ref 属性更有用。它可以很方便地保存任何可变值,其类似于在 class 中使用实例字段的方式。

这是因为它创建的是一个普通 Javascript 对象。而 useRef() 和自建一个 {current: …}
对象的唯一区别是,useRef 会在每次渲染时返回同一个 ref 对象。

请记住,当 ref 对象内容发生变化时,useRef 并不会通知你。变更 .current 属性不会引发组件重新渲染。如果想要在 React
绑定或解绑 DOM 节点的 ref 时运行某些代码,则需要使用回调 ref 来实现。

useRef 有什么作用呢,其实很简单,总共有三种用法

 作用于Dom元素 获取子组件的实例(只有类组件可用) 在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的
 this.xxx useRef使用 作用于Dom元素
const UseRefComp=()=>{ 
		//创建ref
		const inputRef=useRef() 
		const getValue= () => {
		//访问ref
			console.log(inputRef.current.value) }
		//挂载 
		return (
		<div>
		<input ref={inputRef} type="text"> <button onClick={getValue}>获取input的
		值</button> </div>
) }

获取子组件的实例(只有类组件可用)

// 使用 ref 子组件必须是类组件
class Children extends PureComponent {
  render () {
    const { count } = this.props
    return (
      <div>{ count }</div>
    )
  }
}

function App () {
  const [ count, setCount ] = useState(0)
  const childrenRef = useRef(null)
  // const 
  const onClick = useMemo(() => {
    return () => {
      console.log('button click')
      console.log(childrenRef.current)
      setCount((count) => count + 1)
    }
  }, [])
  return (
    <div>
      点击次数: { count }
      <Children ref={childrenRef}  count={count}></Children>
      <button onClick={onClick}>点我</button>
    </div>
    )
}

在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx

简单例子:

function Test(){

const t=useRef(null);

const handleClick = ()=>{
	t.current=setTimeout(()=>{
		console.log('timer')
	},1000)
}
const handleClear = () => clearTimeout(t.current)

return (
	<>
		<button onClick={handleClick}>start</button>
		<button onClick={handleClear}>clear</button>
	</>
)}

有些情况下,我们需要保证函数组件每次 render 之后,某些变量不会被重复申明,比如说 Dom 节点,定时器的 id 等等,在类组件中,我们完全可以通过给类添加一个自定义属性来保留,比如说 this.xxx, 但是函数组件没有 this,自然无法通过这种方法使用,有的朋友说,我可以用useState 来保留变量的值,但是 useState 会触发组件 render,在这里完全是不需要的,我们就需要使用 useRef 来实现了,具体看下面例子

function App () {
  const [ count, setCount ] = useState(0)
  const timer = useRef(null)
  let timer2 
  
  useEffect(() => {
    let id = setInterval(() => {
      setCount(count => count + 1)
    }, 500)

    timer.current = id
    timer2 = id
    return () => {
      clearInterval(timer.current)
    }
  }, [])

  const onClickRef = useCallback(() => {
    clearInterval(timer.current)
  }, [])

  const onClick = useCallback(() => {
    clearInterval(timer2)
  }, [])

  return (
    <div>
      点击次数: { count }
      <button onClick={onClick}>普通</button>
      <button onClick={onClickRef}>useRef</button>
    </div>
    )
}

当我们们使用普通的按钮去暂停定时器时发现定时器无法清除,因为 App 组件每次 render,都会重新申明一次 timer2, 定时器的 id 在第二次 render 时,就丢失了,所以无法清除定时器,针对这种情况,就需要使用到 useRef,来为我们保留定时器 id,类似于 this.xxx,这就是 useRef 的另外一种用法。

你可能感兴趣的:(react)