【react+ts- forwardRef】


引用传递(Ref forwading)是一种通过组件向子组件自动传递 引用ref 的技术。对于应用者的大多数组件来说没什么作用。但是对于有些重复使用的组件,可能有用。例如某些input组件,需要控制其focus,本来是可以使用ref来控制,但是因为该input已被包裹在组件中,这时就需要使用Ref forward来透过组件获得该input的引用。

作者:pipu
链接:https://www.jianshu.com/p/fac884647720/
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

1. 学习资料

JS-react forward ref高阶组件透传-1
JS-react forward ref高阶组件透传-2
TS-react forward ref高阶组件透传

2. 普通input透传

2.1 TS版本

Parent.tsx

import React, { useRef, useState } from 'react'
import Child from './Child';

export default function Parent() {
  const inputRef = useRef<HTMLInputElement>(null);
  const [text,setText] = useState<string>('');
  return (
    <div>
      <button onClick={()=>{
        inputRef.current?.focus();
        setText('');
      }}>父组件内按钮-点击input获取焦点并清空value</button>
      <Child ref={inputRef} text={text} changeVal={(val:string)=>{
        setText(val);
      }}></Child>
    </div>
  )
}

Child.tsx

import React, { ChangeEvent, forwardRef, MutableRefObject, useCallback, useRef } from 'react'

interface Iprops {
  text:string;
  changeVal:Function
}

const Child = forwardRef<HTMLInputElement,Iprops>((props,ref) => {
const localRef = useRef<HTMLInputElement | null>(null);

const onChange = useCallback((e:ChangeEvent<HTMLInputElement>)=>{
  props.changeVal(e.target.value)
},[props]);

return (
  <div>
    <input type="text" value={props.text} ref={el=>{
      localRef.current = el;
      console.log(ref)
      if (typeof ref === 'function') {
        ref(el);
      } else if (ref) {
        (ref as MutableRefObject<HTMLInputElement>).current = el!;
      }
    }} onChange={onChange}/>
    <button onClick={()=>{
      console.log(localRef.current)
      console.log(localRef.current?.value)
      console.log(props.text)
    }}>子组件内按钮-点击获取input输入值</button>
  </div>
)
}) 

export default Child

2.2 JS版本

Child.tsx

import React, { forwardRef, useCallback} from 'react'
const Child = forwardRef((props,ref) => {
	const onChange = useCallback((e)=>{
	  props.changeVal(e.target.value)
	},[props]);

	return (
	  <div>
	    <input type="text" value={props.text} ref={ref} onChange={onChange}/>
	    <button onClick={()=>{
	      console.log(ref.current)
	      console.log(ref.current.value)
	      console.log(props.text)
	    }}>子组件内按钮-点击获取input输入值</button>
	  </div>
	)
}) 

export default Child

3. TS-Antd-Form组价透传

Parent.tsx

import React, { useRef } from 'react'
import type { FormInstance } from 'antd/es/form';
import Child from './Child';

export default function Parent() {
  const addForm = useRef<FormInstance>(null);
  const updateForm= useRef<FormInstance>(null);
  return (
    <div>
      <button onClick={()=>{
        addForm.current?.validateFields()
        	.then((values) => {
        		console.log(values);
        	})
        	.catch((err) => {
		        console.log(err);
		     });
        
      }}>父组件内按钮-点击input获取焦点并清空value</button>
      <UserForm ref={addForm} regionList={regionList} roleList={roleList} />
      <UserForm ref={updateForm} regionList={regionList} roleList={roleList} />
    </div>
  )
}

Child.tsx

import React, { forwardRef, MutableRefObject, Ref, useEffect} from "react";
import { Form } from "antd";
import type { FormInstance } from 'antd/es/form';

interface UserFormProps {
  isUpdateRegionDisabled?:boolean;
  regionList:any[];
  roleList:any[];
}
const assignRefs = <T extends unknown>(...refs: Ref<T | null>[]) => {
  return (node: T | null) => {
    refs.forEach((r) => {
      if (typeof r === "function") {
        r(node);
      } else if (r) {
        (r as MutableRefObject<T | null>).current = node;
      }
    });
  };
};

const UserForm = forwardRef<FormInstance,UserFormProps>((props,ref)=>{
	const localRef = React.useRef<FormInstance | null>(null);
	useEffect(() => {
    	console.log('localRef',localRef.current)
  	}, [props]);
	return (
		<Form layout="vertical" ref={assignRefs(localRef, ref)}></Form>
	)
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值