惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
Google DeepMind News
Google DeepMind News
腾讯CDC
G
Google Developers Blog
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
爱范儿
爱范儿
Engineering at Meta
Engineering at Meta
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
有赞技术团队
有赞技术团队
Jina AI
Jina AI
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
M
MIT News - Artificial intelligence
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
美团技术团队
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志

博客园 - 君临天下之徐少

nvm安装 Homebrew 安装 Less的优点 什么是nrm js 处理大数相减 谷歌刷题插件安装 SSL certificate problem: unable to get local issuer certificate 错误解决 常用命令 Mac安装Nvm Node开发环境 解决Mac安装Homebrew失败 Canvas学习:globalCompositeOperation详解 React.CreateContext html让容器居中,css让容器水平垂直居中的7种方式 js下载文件防止白屏 GitHub上README.md编写教程(基本语法) 微信字体大小调整导致的H5页面错乱问题处理 G6-Editor 编辑器入门使用教程 git reset 加不加 --hard的区别 taro, h5拨打电话和发送短信
React函数式组件值之useRef()和useImperativeHandle()
君临天下之徐少 · 2022-12-01 · via 博客园 - 君临天下之徐少

一、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>
    )
}