useImperativeHandle可以给React.forward处理后的函数组件接收到的ref对象拓展功能
方式一(不使用forwardRef)
import React, { forwardRef, useImperativeHandle, useState } from 'react'
// 定义子组件 CustomInput,并接受 ref 传递
const CustomInput = (props: any) => {
const { onRef } = props
const [value, setValue] = useState('')
// 创建一个内部 ref 并绑定到 input 元素上
const inputRef = React.useRef(null)
// 使用 useImperativeHandle 来暴露 focus 方法
useImperativeHandle(onRef, () => ({
// 父组件可以通过 ref 调用此方法聚焦输入框
clearInput: clearInput,
}))
const clearInput = () => {
setValue('')
// 如果 inputRef 已经关联到 DOM 元素,则同时触发其值清空
if (inputRef.current) {
inputRef.current.value = ''
}
}
return (
<>
<input
ref={inputRef}
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</>
)
}
// 在父组件中使用 CustomInput 并获取 ref
function MyApp() {
const inputRef = React.useRef(null)
// 当需要时,可以直接调用 ref 上的方法
const handleFocus = () => {
if (inputRef.current) {
inputRef.current.clearInput()
}
}
return (
<>
<CustomInput onRef={inputRef} />
<button onClick={handleFocus}>Focus the Input</button>
</>
)
}
export default MyApp
方式二(使用forwardRef)
import React, { forwardRef, useImperativeHandle, useState } from 'react'
// 定义子组件 CustomInput,并接受 ref 传递
const CustomInput = forwardRef((props, ref) => {
const [value, setValue] = useState('')
// 创建一个内部 ref 并绑定到 input 元素上
const inputRef = React.useRef(null)
// 使用 useImperativeHandle 来暴露 focus 方法
useImperativeHandle(ref, () => ({
// 父组件可以通过 ref 调用此方法聚焦输入框
clearInput: clearInput,
}))
const clearInput = () => {
setValue('')
// 如果 inputRef 已经关联到 DOM 元素,则同时触发其值清空
if (inputRef.current) {
inputRef.current.value = ''
}
}
return (
<>
<input
ref={inputRef}
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</>
)
})
// 在父组件中使用 CustomInput 并获取 ref
function MyApp() {
const inputRef = React.useRef(null)
// 当需要时,可以直接调用 ref 上的方法
const handleFocus = () => {
if (inputRef.current) {
inputRef.current.clearInput()
}
}
return (
<>
<CustomInput ref={inputRef} />
<button onClick={handleFocus}>Focus the Input</button>
</>
)
}
export default MyApp