ForwardRef?useImperativeHandle方法demo
更新時間:2023年03月19日 09:26:31 作者:好好吃飯好好睡覺
這篇文章主要為大家介紹了ForwardRef?useImperativeHandle方法demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
一、獲取Ref的方式
- 使用字符串
- 使用函數(shù)
- 使用Ref對象(最常見)
- 使用createRef
export class RefTest extends React.Component {
currentDom: React.RefObject<HTMLDivElement> = React.createRef();
currentChildren: React.LegacyRef<Children> = React.createRef();
render() {
console.log(this.currentChildren, this.currentDom);
return (
<>
<div ref = { this.currentDom }>你好</div>
<Children ref = { this.currentChildren}></Children>
</>
)
}
}

- 使用useRef
export const RefTest = () => {
const currentDom = useRef(null);
const currentChildren = useRef(null);
useEffect(() => {
console.log(currentChildren, currentDom, '這里也可以打印出來了');
},[])
return (
<>
<div ref = { currentDom }>你好</div>
<Children ref = { currentChildren }></Children>
</>
)
}
二、Ref實現(xiàn)組件通信
- 既然ref可以獲取到子組件的實例,那么就可以拿到子組件上的狀態(tài)和方法,從而可以實現(xiàn)組件之間的通信
來個極簡版

import React, { useEffect } from 'react';
class Son extends React.Component{
state={
sonValue:''
}
render(){
return <div>
<div>子組件的信息: {this.state.sonValue}</div>
<div>對父組件說</div>
<input onChange{(e)=>this.props.setFather(e.target.value)}/>
</div>
}
}
export default function Father(){
const [ fatherValue , setFatherValue ] = React.useState('')
const sonRef = React.useRef(null)
return <div>
<div>父組件的信息: {fatherValue}</div>
<div>對子組件說</div>
<input onChange = { (e) => sonRef.current.setState( {sonValue: e.target.value})}/>
<Son ref={sonRef} setFather={setFatherValue}/>
</div>
}

三、ForwardRef
- 上面說的三種都是組件去獲取其DOM元素或者子組件的實例,當開發(fā)變得復雜時,我們可能有將ref跨層級捕獲的需求,也就是可以將ref進行轉(zhuǎn)發(fā)
比如跨層級獲取ref信息

- 來個例子, 我們希望能夠在GrandFather組件獲取到Son組件中
![圖片轉(zhuǎn)存失敗,建議將圖片保存下來直接上傳
import React from 'react';
interface IProps {
targetRef: React.RefObject<HTMLDivElement>
otherProps: string
}
interface IGrandParentProps {
otherProps: string
}
class Son extends React.Component<IProps> {
constructor(props) {
super(props);
console.log(props,'son中的props');
}
render() {
// 最終目標是獲取該DOM元素的信息
return <div ref= { this.props.targetRef }>真正目的是這個</div>
}
}
class Farther extends React.Component<IProps> {
constructor(props) {
super(props)
console.log(props, 'father中的props');
}
render() {
return (
// 繼續(xù)將ref傳給Son
<Son targetRef={this.props.targetRef} {...this.props} />
)
}
}
// 在這里使用了forwardRef, 相當于把傳入的ref轉(zhuǎn)發(fā)給Father組件
const ForwardRef = React.forwardRef((props: IGrandParentProps, ref: React.RefObject<HTMLDivElement>)
=> <Farther targetRef={ref} {...props}/>)
image.png(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5d49e7ff4ec940b28dcb3a780fd5c0a7~tplv-k3u1fbpfcp-watermark.image?)
export class GrandFather extends React.Component {
currentRef:React.RefObject<HTMLDivElement> = React.createRef();
componentDidMount() {
// 獲取到的Ref信息
console.log(this.currentRef, 'componentDidMount');
}
render() {
return (
<ForwardRef ref={this.currentRef} otherProps = '正常傳遞其他props' />
)
}
}
]()
- 打印結(jié)果: 其實就是利用了forwardRef,把 ref 變成了可以通過 props 傳遞和轉(zhuǎn)發(fā)

四、 useImperativeHandle
- 上面我們一直說的都是獲取子組件的實例,但是實際上我們函數(shù)組件是沒有實例的,故我們需要借助useImperativeHandle, 使用forwardRef+useImperativeHandle就可以在函數(shù)組件中流暢地使用ref
- useImperativeHandle可以傳入三個參數(shù):
- ref: 可以接受forwardRef傳入的ref
- handleFunc: 返回值作為暴露給父組件的ref對象
- deps: 依賴項,當依賴項改變的時候更新形成的ref對象
看完參數(shù)其實就能夠清楚地知道它的作用了,可以通過forwardRef+useImperativeHandle自定義獲取到的ref信息
再來兩個簡單例子:
import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react"
const ForwardItem = forwardRef((props, ref) => {
const [sonValue, setSonValue] = useState('修改之前的值');
useImperativeHandle(ref, () => ({
setSonValue,
}))
return (
<div>子組件的值: {sonValue}</div>
)
})
export const Father = () => {
const testRef = useRef(null);
useEffect(() => {
console.log(testRef.current, 'ref獲取到的信息')
})
const changeValue = () => {
const DURATION = 2000;
setTimeout(() => {
testRef.current.setSonValue('我已經(jīng)修改值啦')
},DURATION)
}
return (
<>
<ForwardItem ref={ testRef }/>
<button onClick={() => changeValue()}>2s后修改子組件ForwardItem的值</button>
</>
)
}

- 父組件希望直接調(diào)用函數(shù)子組件的方法
- 這里讓useImperativeHandle形成了有setSonValue的ref對象,然后再在父組件調(diào)用該方法
- 父組件希望獲取到子組件的某個DOM元素
const ForwardItem = forwardRef((props, ref) => {
const elementRef: RefObject<HTMLDivElement> = useRef();
useImperativeHandle(ref, () => ({
elementRef,
}))
return (
<div ref = { elementRef }>我是一個子組件</div>
)
})
export const Father = () => {
const testRef = useRef(null);
useEffect(() => {
console.log(testRef.current, 'ref獲取到的信息')
})
return (
<>
<ForwardItem ref={ testRef }/>
</>
)
}

當然useRef還可以在函數(shù)組件中緩存數(shù)據(jù),這個就不多叨叨啦,更多關于ForwardRef useImperativeHandle的資料請關注腳本之家其它相關文章!
相關文章
react native實現(xiàn)監(jiān)控手勢上下拉動效果
這篇文章主要為大家詳細介紹了react native實現(xiàn)監(jiān)控手勢上下拉動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-05-05
詳解React setState數(shù)據(jù)更新機制
這篇文章主要介紹了React setState數(shù)據(jù)更新機制的相關資料,幫助大家更好的理解和學習使用React框架,感興趣的朋友可以了解下2021-04-04
flouting?ui定位組件完美替代ant?deisgn使用詳解
這篇文章主要為大家介紹了flouting?ui定位組件完美替代ant?deisgn使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-11-11
解析TypeError:import_react_native.AppState.removeEventListener
這篇文章主要為大家介紹了TypeError:import_react_native.AppState.removeEventListener?is?not?a?function問題解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09

