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

推荐订阅源

美团技术团队
罗磊的独立博客
SecWiki News
SecWiki News
The Register - Security
The Register - Security
The GitHub Blog
The GitHub Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 三生石上(FineUI控件)
S
Schneier on Security
IT之家
IT之家
博客园 - 聂微东
T
The Exploit Database - CXSecurity.com
Recorded Future
Recorded Future
大猫的无限游戏
大猫的无限游戏
Know Your Adversary
Know Your Adversary
Latest news
Latest news
Vercel News
Vercel News
G
GRAHAM CLULEY
D
DataBreaches.Net
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
SegmentFault 最新的问题
博客园_首页
雷峰网
雷峰网
T
Tenable Blog
Spread Privacy
Spread Privacy
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
酷 壳 – CoolShell
酷 壳 – CoolShell
Cisco Talos Blog
Cisco Talos Blog
V
Visual Studio Blog
J
Java Code Geeks
博客园 - Franky
The Cloudflare Blog
Apple Machine Learning Research
Apple Machine Learning Research
C
CERT Recently Published Vulnerability Notes
T
Threatpost
Google DeepMind News
Google DeepMind News
F
Fortinet All Blogs
P
Privacy International News Feed
T
Threat Research - Cisco Blogs
T
The Blog of Author Tim Ferriss
V
Vulnerabilities – Threatpost
Recent Announcements
Recent Announcements
Blog — PlanetScale
Blog — PlanetScale
Security Latest
Security Latest
U
Unit 42
M
MIT News - Artificial intelligence
Y
Y Combinator Blog
K
Kaspersky official blog
有赞技术团队
有赞技术团队
B
Blog
腾讯CDC

博客园 - 君临天下之徐少

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