React函数式组件值之useRef()和useImperativeHandle()

一、useRef

  useRef共有两种用法,获取子组件的实例(只有类组件可用),在函数组件中的一个全局变量,不会因为重复 render 重复申明, 类似于类组件的 this.xxx。

 

  1. useRef 在使用的时候,可以传入默认值来指定默认值,需要使用的时候,访问 ref.current 即可访问到组件实例:

// 使用 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 onClick = useMemo(() => {
    return () => {
      console.log(childrenRef.current)
      setCount((count) => count + 1)
    }
  }, [])
  return (
    <div>
      点击次数: { count }
      <Children ref={childrenRef}  count={count}></Children>
      <button onClick={onClick}>点我</button>
    </div>
    )
}

 2.  有些情况下,我们需要保证函数组件每次 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>
    )
}

二、useImperativeHandle

  useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值,说简单点就是,子组件可以选择性的暴露给副组件一些方法,这样可以隐藏一些私有方法和属性,官方建议,useImperativeHandle应当与 forwardRef 一起使用,具体如何使用看下面例子

function Child (props, ref) {
  const child = useRef()
  const introduce = useCallback (() => {
    console.log('i can sing, jump, rap, play basketball')
  }, [])
  useImperativeHandle(ref, () => ({introduce}));
  return (
    <div ref={child}> { props.count }</div>
  )
}
const ChildChild = forwardRef(Child)
function App () {
  const [ count, setCount ] = useState(0)
  const childRef = useRef(null)
  const onClick = useCallback (() => {
    setCount(count => count + 1)
    childRef.current.introduce()
  }, [])
  return (
    <div>
      点击次数: { count }
      <ChildChild ref={childRef}  count={count}></ChildChild>
      <button onClick={onClick}>点我</button>
    </div>
    )
}

 

posted @ 2022-12-01 16:56  君临天下之徐少  阅读(594)  评论(0编辑  收藏  举报