useImperativeHandle 类似Vue3中的 defineExpose 宏函数的用法,可以将一些状态和dom暴露给父组件使用
在react19版本,ref可以直接由props接收, 父组件传入ref可以直接拿取子组件的dom节点,但如果我们不想让父组件直接访问子组件的dom,使用useImperativeHandle钩子是一个好办法
useImperativeHandle传入两个参数:ref和一个返回对象的函数,对象中 可传入需要暴露出去的状态和方法、dom对象等
Father.tsx
export default function AddGoods() {
const son = useRef<SonRefContent>(null)
useEffect(() => {
console.log('son:', son.current);
if (son.current) {
son.current.changeColor()
}
}, [])
return (
<>
<Son ref={son} />
<button onClick={() => son.current?.setCount(son.current.count + 1)}>++</button>
</>
)
}
Son.tsx
import React, { useImperativeHandle, useRef, useState } from 'react'
export interface SonProps {
ref: SonRef
}
export type SonRef = React.RefObject<RefContent | null>
export type SonRefContent = {
changeColor: () => void,
count: number, setCount: React.Dispatch<React.SetStateAction<number>>
}
//react19之后,ref直接在props中
export default function Son({ ref }: SonProps) {
const ele = useRef<HTMLDivElement>(null)
const [count, setCount] = useState(0)
useImperativeHandle(ref, () => ({
changeColor: () => {
if (ele.current) {
ele.current.style.color = 'red'
}
},
count, setCount
}))
return (
<div ref={ele}>Son{count}</div>
)
}