目录:

  1. 简介
  2. useRef
  3. forwardRef
  4. useImperativeHandle
  5. 回调Ref

简介

大家都知道React中的ref属性可以帮助我们获取子组件的实例或者Dom对象,进而对子组件进行修改,是一个很方便的特性。在传统类组件中,我们通过使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素来使用。而随着hooks的越来越广泛的使用,我们有必要了解一下在函数式组件中,如何使用Ref.

想要在函数式组件中使用Ref,我们必须先了解两个Api,useRefforwardRef

useRef

const refContainer = useRef(initialValue);

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

下面看一个例子

function TextInputWithFocusButton() {
// 关键代码
const inputEl = useRef(null);
const onButtonClick = () => {
// 关键代码,`current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
// 关键代码
<input ref={inputEl} type="text" /> <button onClick={onButtonClick}>Focus the input</button>
</>
);
}

效果如下

可以看到我们点击button,先通过useRef创建一个ref对象inputEl,然后再将inputEl赋值给inputref,最后,通过inputEl.current.focus()就可以让input聚焦。

然后,我们再想下,如果input不是个普通的dom元素,而是个组件,该怎么办呢?

这就牵扯到另外一个api,forwardRef

forwardRef

我们修改一下上面的例子,将input单独封装成一个组件TextInput

const TextInput =  forwardRef((props,ref) => {
return <input ref={ref}></input>
})

然后用TextInputWithFocusButton调用它

function TextInputWithFocusButton() {
// 关键代码
const inputEl = useRef(null);
const onButtonClick = () => {
// 关键代码,`current` 指向已挂载到 DOM 上的文本输入元素
inputEl.current.focus();
};
return (
<>
// 关键代码
<TextInput ref={inputEl}></TextInput>
<button onClick={onButtonClick}>Focus the input</button>
</>
);
}

可以看到React.forwardRef 接受一个渲染函数,其接收 props 和 ref 参数并返回一个 React 节点。

这样我们就将父组件中创建的ref转发进子组件,并赋值给子组件的input元素,进而可以调用它的focus方法。

至此为止,通过useRef+forwardRef,我们就可以在函数式组件中使用ref了。当然,这篇文章还远不止如此,下面还要介绍两个重要的知识点useImperativeHandle回调Ref,结合上面两个api,让你的代码更加完美。

useImperativeHandle

有时候,我们可能不想将整个子组件暴露给父组件,而只是暴露出父组件需要的值或者方法,这样可以让代码更加明确。而useImperativeHandleApi就是帮助我们做这件事的。

语法:

useImperativeHandle(ref, createHandle, [deps])

useImperativeHandle 可以让你在使用 ref 时自定义暴露给父组件的实例值。

一个例子

React函数式组件使用Ref的更多相关文章

  1. React 函数式组件的 Ref 和子组件访问(useImperativeHandle)

    引入:如何调用函数式组件内部的方法 对于 React 中需要强制修改子组件的情况,React 提供了 Refs 这种解决办法,使得我们可以操作底层 DOM 元素或者自定的 class 组件实例.除此之 ...

  2. 如何对 React 函数式组件进行优化

    文章首发个人博客 前言 目的 本文只介绍函数式组件特有的性能优化方式,类组件和函数式组件都有的不介绍,比如 key 的使用.另外本文不详细的介绍 API 的使用,后面也许会写,其实想用好 hooks ...

  3. React函数式组件和类组件[Dan]

    一篇对Dan的 How Are Function Components Different from Classes? 一文的个人阅读总结,内容来自于此.强烈推荐阅读 Dan Abramov.的博客. ...

  4. React函数式组件的性能优化

    优化思路 主要优化的方向有2个: 减少重新 render 的次数.因为在 React 里最重(花时间最长)的一块就是 reconction(简单的可以理解为 diff),如果不 render,就不会 ...

  5. 函数式组件中实现Antd打开Modal后其Input框自动聚焦(focus)到文字的最后

    目前React使用函数式组件已经成为趋势, 如何把React函数式组件用好, 提高性能, 从而实现业务需求也成为了一种能力的体现......咳咳咳, 进入正题: 现实场景需求 我想实现这一个需求, 父 ...

  6. react 中的无状态函数式组件

    无状态函数式组件,顾名思义,无状态,也就是你无法使用State,也无法使用组件的生命周期方法,这就决定了函数组件都是展示性组件,接收Props,渲染DOM,而不关注其他逻辑. 其实无状态函数式组件也是 ...

  7. React Native中ref的用法(通过组件的ref属性,来获取真实的组件)

    ref是什么? ref是组件的特殊属性,组件被渲染后,指向组件的一个引用.可以通过组件的ref属性,来获取真实的组件.因为,组件并不是真正的DOM节点,而是存在于内存中的一种数据结构,称为虚拟的DOM ...

  8. react创建组件的几种方式及其区别

    react创建组件有如下几种方式 ①.函数式定义的无状态组件 ②.es5原生方式React.createClass定义的组件   ③.es6形式的extends React.Component定义的组 ...

  9. React创建组件的三种方式及其区别

    内容转载于http://www.cnblogs.com/wonyun/p/5930333.html React推出后,出于不同的原因先后出现三种定义react组件的方式,殊途同归; 具体的三种方式: ...

随机推荐

  1. 【5min+】 这些C#的运算符您都认识吗?

    系列介绍 [五分钟的dotnet]是一个利用您的碎片化时间来学习和丰富.net知识的博文系列.它所包含了.net体系中可能会涉及到的方方面面,比如C#的小细节,AspnetCore,微服务中的.net ...

  2. Codeforces_837

    A.扫一遍. #include<bits/stdc++.h> using namespace std; int n; string s; int main() { cin >> ...

  3. Educational Codeforces Round 57

    2018.12.28  22:30 看着CF升高的曲线,摸了摸自己的头发,我以为我变强了,直到这一场Edu搞醒了我.. 从即将进入2018年末开始,开启自闭场集合,以纪念(dian)那些丢掉的头发 留 ...

  4. 题解 SDOI2010 【栗栗的书架】

    \[ Preface \] 看到这题洛谷标签有 主席树 ,还以为是什么二维主席树的玄学做法(雾 \[ Description \] 给出一个 \(R×C\) 的矩阵. 一共 \(m\) 次询问,每次询 ...

  5. Go语言实现:【剑指offer】栈的压入、弹出序列

    该题目来源于牛客网<剑指offer>专题. 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5 ...

  6. CSS实现按钮点击后根据背景色加深效果-一颗优雅草bigniu

    具体代码如下 button{ position: relative; } button:active::before { display: block; content: ''; position: ...

  7. javascript Date对象 js全部的 时间属性 和 方法

    Date() 返回当日的日期和时间. getTime() 返回 1970 年 1 月 1 日至今的毫秒数. getDate() 从 Date 对象返回一个月中的某一天 (1 ~ 31).天 getDa ...

  8. 数据算法 --hadoop/spark数据处理技巧 --(3.左外连接 4.反转排序)

    三. 左外连接 考虑一家公司,比如亚马逊,它拥有超过2亿的用户,每天要完成数亿次交易.假设我们有两类数据,用户和交易: users(user_id,location_id) transactions( ...

  9. Cacti被监控机器 配置 snmp协议

    SNMP(Simple Network Management Protocol,简单网络管理协议)的前身是简单网关监控协议(SGMP),用来对通信线路进行管理.         snmpd.conf的 ...

  10. C语言四

    c语言循环结构 为什么用循环? C语言中的循环主要分为三种:while循环,do...while循环 for循环 while循环:先判断条件是否成立,如果条件成立将执行其下的循环体,如果条件不成立一次 ...