react之useRef和createRef

一、useRef和createRef

1. 作用于普通DOM

在这里插入图片描述

import { Input, Button } from 'antd';
import { useRef, createRef } from 'react';

import type { InputRef } from 'antd';

const RefDemo = () => {
  const inputEL = useRef<InputRef>(null);
  const inputEL2 = useRef<HTMLInputElement>(null);
  const inputEL3 = createRef<HTMLInputElement>();

  const getInput = () => {
    console.log('antd DOM', inputEL.current?.input?.value);
    console.log('原生 DOM', inputEL2.current?.value);
    console.log('createRef', inputEL3.current?.value);
  };

  return (
    <div>
      <p>antd Input:<Input ref={inputEL} style={{width: 167}} /></p>
      <p>原生 Input:<input type="text" ref={inputEL2} /></p>
      <p>createRef Input:<input type="text" ref={inputEL3} /></p>
      <p><Button onClick={getInput}>获取Input Value</Button></p>
    </div>
  );
};

export default RefDemo;
2. 作用于子组件,需要用到两个方法 useImperativeHandleforwardRef
  • forwardRef:包裹要添加ref的子组件,有两个参数,组件的props和组件的ref
  • useImperativeHandle:两个参数,组件的 ref 和一个回调函数,返回值是子组件的方法或者变量,提供给父组件调用
  • 注意!在父组件中使用 ref 去更新子组件,只是子组件更新,父组件不会同步更新,需要手动更新
    在这里插入图片描述
import { Button } from 'antd';
import { useRef, useImperativeHandle, forwardRef, useState } from 'react';

const Child = forwardRef((props, ref) => {

  const [count, setCount] = useState<number>(0);

  useImperativeHandle(ref, () => ({
    count: count,
    changeCount() {
      setCount(count + 1);
    }
  }));

  return (
    <div>
      <p>子组件count: { count }</p>
    </div>
  );
});

type ChildRefType = {
  count: number,
  changeCount: () => void;
}
const RefDemo = () => {
  const childRef = useRef<ChildRefType>();

  const [reload, setReload] = useState<boolean>(false);

  const changeChild = () => {
    childRef.current?.changeCount();
  };

  return (
    <div>
      <p>
        父组件:count:{childRef.current?.count}
        <Button onClick={changeChild}>调用子组件的方法</Button>
        <Button onClick={() => setReload(!reload)}>手动更新父组件</Button>
      </p>
      <Child ref={childRef} />
    </div>
  );
};

export default RefDemo;
  • 注意!此方法不适用于createRef,原因如下,每次父组件渲染都会重新创建ref,所获取的值都为undefined

二、useRef和createRef区别

  • createRef会在组件每次渲染的时候重新创建
  • useRef只会在组件首次渲染时创建
    在这里插入图片描述
import { useState, useRef, createRef } from 'react';
import { Button } from 'antd';

const RefDemo = () => {
  
  const [count, setCount] = useState<number>(0);
  
  const inputEL = useRef<HTMLInputElement>(null);
  const inputEL2 = createRef<HTMLInputElement>();

  const showCount = () => {
    console.log('useRef Input:', inputEL.current?.value);
    console.log('createRef Input:', inputEL2.current?.value);
  };

  const updateComponent = () => {
    setCount(count + 1);
  };

  console.log(inputEL.current?.value, inputEL2.current?.value, `组件${count === 0 ? '初' : count}次渲染`);

  return(
    <div>
      <p>useRef Input:<input type="text" ref={inputEL} /></p>
      <p>createRef Input:<input type="text" ref={inputEL2} /></p>
      <p><Button onClick={updateComponent}>重新渲染</Button></p>
      <p><Button onClick={showCount}>show value</Button></p>
    </div>
  );
};

export default RefDemo;
  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值