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