使用useImperativeHandle时父组件第一次没拿到子组件方法
背景需求
一个tab两个按钮A、B,默认选中的A,当点击到B时需要显示B对应的图表。考虑到B的图表在页面加载时已经初始化完成,所以点击B时再调用图表的resize方法。由于tab中的图表是写在子组件里,所以通过useImperativeHandle实现父组件调用子组件方法,React版本"react": "^18.1.0"
,代码如下
- 父组件:
const childRef = useRef()
const item = [{
name: 'XXXX',
content: <RunningRecord cRef={childRef} />,
handClick: childRef.current?.resizeChart
}]
return <>
……
<li onClick={() => {
setTimeout(() => {
console.log('~~item.handClick',item.handClick)
item.handClick?.()
}, 200)
}}
key={item.name}>
{item.name}
</li>
……
<RunningRecord cRef={childRef} />
</>
- 子组件:
function RunningRecord({ cRef }) {
……
useImperativeHandle(cRef,()=>({
resizeChart:()=> {dosomething……}
}))
问题
这样写在本地开发模式中正常运行,但生产环境中父组件首次加载不能拿到子组件的方法,需tab切换到A再次且到B才行。猜想原因,大概在生产环境中,父组件把子组件暴露出来的方法绑定到UI中的点击事件中,而子组件初始化的时机晚,初始完成后并没有把事件传回来。
这个猜想不一定准确,欢迎知道的小伙伴们补充。
解决方法
在父组件中,将子组件赋值的过程放在useEffect中,不写依赖项参数(不是没有依赖的空数组),再运行,一切正常。
const usageRecordData = [{
name: 'XXXX',
content: <RunningRecord cRef={childRef} />,
}]
useEffect(() => {
usageRecordData[1].handClick = childRef.current?.resizeChart
})