useRef和createRef

在react中,我们可以使用ref来获取组件示例或者DOM元素。
一般使用方法:

const ref = useRef(initialValue);
<input ref={ref} />

注意:

  1. useRef返回一个可变的 ref 对象,该对象只有个 current 属性,初始值为传入的参数( initialValue );
  2. 返回的 ref 对象在组件的整个生命周期内保持不变,除非手动修改
  3. 更新 current 值时并不会 re-render ,这是与 useState 不同的地方;
  4. useRef也可以用来区分初始渲染还是更新(通过current有没值);
拓展1:createRef
import React from 'react';
import './App.css';

class App extends React.Component {
	componentDidMount() {
	    this.refIns = React.createRef();
	}
	render() {
	    return (
            <div>
	           <div id="refIns" ref={this.refIns}>hello</div>
	        </div>
	    );
	}
}

与useRef类似,createRef也是用来创建mutable object,该object也只包含一个current属性,同样的,当current的值发生改变时,页面不会重新渲染。但是,createRef与useRef也存在些许不同:

  1. useRef是use hooks的一种,一般用于function组件,而createRef一般用于class组件;
  2. 由useRef创建的ref对象在组件的整个生命周期内都不会改变,但是由createRef创建的ref对象,组件每更新一次,ref对象就会被重新创建

事实上,useRef之所以出现,就是因为在函数式组件中使用createRef创建ref时存在弊端(组件每次更新,ref对象就会被重新创建)。

拓展2:ref对象可以用于保存数据

实际上,不管是useRef还是createRef,他们创建的ref对象不仅是DOM示例,还可以用于存储数据的。

function App() {
  const valRef = React.useRef(80);
  return <div>
    value: {valRef.current}
    <button onClick={() => valRef.current += 1}>+</button>
  </div>
}

你会发现,不管你怎么点击按钮,value的值都会是80,并不会发生变化,这是因为ref对象的改变,并不会触发页面的更新。

function App() {
  const valRef = React.useRef(80);
  const [, setChange] = React.useState();
  return <div style={{padding: "100px 200px"}}>
      value: {valRef.current}
      <button onClick={() => {
        valRef.current += 1;
        setChange({});
      }}>+
      </button>
    </div>
 }

当然,如果你在function组件中使用createRef实现以上功能,你就能够发现问题所在。

function App() {
    const valRef = React.createRef();
    const [, setChange] = React.useState();
    return <div style={{padding: "100px 200px"}}>
      value: {valRef.current}
      <button onClick={() => {
          valRef.current = 80;
          setChange({});
      }}>+
      </button>
    </div>
}

不管你怎么点击按钮,value始终没有值,因为每次触发组件渲染,ref对象都会被重新创建。

拓展3:获取子组件的属性或方法

例如:在父组件中调用子组件中的一个方法
一般做法,父组件通过给子组件设置ref,然后通过ref.current来调用子组件的方法

import React, { MutableRefObject, useState, useEffect, useRef, useCallback} from 'react'
interface IProps {
    //prettier-ignore
    label: string,
    cRef: MutableRefObject<any>
}
const ChildInput: React.FC<IProps> = (props) => {
    const { label, cRef } = props
    const [value, setValue] = useState('')
    const handleChange = (e: any) => {
        const value = e.target.value
        setValue(value)
    }
    const getValue = useCallback(() => {
        return value
    }, [value])
    useEffect(() => {
        if (cRef && cRef.current) {
            cRef.current.getValue = getValue()
        }
    }, [getValue])
    return (
        <div>
            <span>{label}:</span>
            <input type="text" value={value} onChange={handleChange} />
        </div>
    )
}

const ParentCom: React.FC = (props: any) => {
    const childRef: MutableRefObject<any> = useRef({})
    const handleFocus = () => {
        const node = childRef.current
        alert(node.getValue())
    }
    return (
        <div>
            <ChildInput label={'名称'} cRef={childRef} />
            <button onClick={handleFocus}>focus</button>
        </div>
    )
}
export default ParentCom

但是,这种做法其实是可以的,但是看起来并不优雅,需要自定义一个属性传入子组件。

第二种做法,通过useImperativeHandle,配合forwardRef。

useImperativeHandle:在函数式组件中,用于定义暴露给父组件的ref方法,用来限制子组件对外暴露的信息,只有useImperativeHandle第二个参数定义的属性跟方法才可以在父组件获取到。(解决直接使用userRef暴露子组件所有属性和方法的弊端)
forwardRef:将父类的ref作为参数,传入函数式组件中(直接为子组件创建ref属性,而不是将ref属性传给子组件,子组件再为某个DOM元素赋值)。

```JavaScript
import React, { MutableRefObject, useState, useImperativeHandle, useRef, forwardRef, useCallback } from 'react'
interface IProps {
    label: string
}
let ChildInput = forwardRef((props: IProps, ref: any) => {
    const { label } = props
    const [value, setValue] = useState('')
    // 作用: 减少父组件获取的DOM元素属性,只暴露给父组件需要用到的DOM方法
    // 参数1: 父组件传递的ref属性
    // 参数2: 返回一个对象,父组件通过ref.current调用对象中方法
    useImperativeHandle(ref, () => ({
        getValue
    }))
    const handleChange = (e: any) => {
        const value = e.target.value
        setValue(value)
    }
    const getValue = useCallback(() => {
        return value
    }, [value])
    return (
        <div>
            <span>{label}:</span>
            <input type="text" value={value} onChange={handleChange} />
        </div>
    )
})
const ParentCom: React.FC = (props: any) => {
    const childRef: MutableRefObject<any> = useRef({})
    const handleFocus = () => {
        const node = childRef.current
        alert(node.getValue())
    }
    return (
        <div>
            <ChildInput label={'名称'} ref={childRef} />
            <button onClick={handleFocus}>focus</button>
        </div>
    )
}
export default ParentCom

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: useRefcreateRef都是React中用于获取组件或DOM元素的引用的方法,但它们有一些区别。 useRef是一个React Hook,可以在函数组件中使用。它返回一个可变的ref对象,可以在组件的整个生命周期中使用。useRef通常用于保存组件的状态,或者在函数组件中获取DOM元素的引用。 createRef是一个类方法,只能在类组件中使用。它返回一个不可变的ref对象,可以在组件的整个生命周期中使用。createRef通常用于在类组件中获取DOM元素的引用。 总之,useRef适用于函数组件,createRef适用于类组件。 ### 回答2: 在React中,Refs提供了一种访问DOM节点或React组件实例的方式。Refs有两种方式来创建:useref和creatrefUserefReact16.8版本引入的一种新方式,它返回一个可变的引用对象,可以通过访问其current属性来获取引用的值。Useref的优点是可以在函数组件中方便地创建ref,而不必使用类组件中的回调方式。Useref的使用方式类似于useState,可以在函数组件中使用,还可以在定时器或其他任何需要保持对DOM节点或React组件实例的引用的情况下使用。 Createref是class组件中用来创建refs的标准方式。当class组件使用createref时,它返回一个对象,该对象可以传递给任何React元素的ref属性,并且可以使用该对象的current属性来访问该元素的引用值。Createref的优点是可以更细粒度地控制引用的创建和销毁,并且可以使用它来访问单个或多个DOM节点或React组件实例。但是,createref只能在class组件中使用,在函数组件中无法使用。 总的来说,useref是在函数组件中方便地创建ref的利器,而createref可以在class组件中更好地控制ref的生命周期和使用范围。在选择使用哪种方式时,我们可以根据组件的类型、具体功能和个人偏好来决定。 ### 回答3: userefcreateref都是React中用来操作ref的方法。在React中,我们经常需要获取DOM元素的引用或者子组件的引用。在这个时候,ref就是用来实现这个功能的。 首先,我们需要理解什么是refref实际上是React提供的一种机制,允许我们直接访问DOM元素或者子组件。通过ref,我们可以获取DOM元素或者子组件的引用,并且可以直接操作他们。refReact组件和原生DOM之间的桥梁,使用ref可以让我们访问到DOM并进行操作。 在React中,我们可以使用createRef方法和useRef函数来创建ref对象。 useRef是一个React中的功能性Hook,它返回一个可变的ref对象。useRef能够关联组件中文本输入框、CheckBox等等元素。useRef可以自动创建一个空的ref容器,它会在组件渲染时保持不变,这个ref容器中会保存一个DOM元素或者子组件的引用,我们可以通过这个引用来访问DOM元素或子组件。 createRefReact中的一个原始API,createRef方法会返回一个ref对象。我们可以在组件中创建一个ref对象,将其传递给需要引用的DOM元素或子组件。当组件渲染时,ref引用将被填充为组件中的DOM元素或子组件的引用。我们可以通过这个引用来访问DOM元素或子组件。 总的来说,userefcreateref的区别在于实现方式上的不同。通过useRef创建的ref对象是一个可变的对象,我们可以通过改变它的值来实现对DOM元素或子组件的引用。而通过createref创建的ref对象是一个不可变对象,它只能通过组件的setState方法来改变。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值