SoFunction
Updated on 2025-04-07

The problem of the parent component not getting the child component for the first time when using useImperativeHandle

Use useImperativeHandle parent component to not get the child component for the first time

Background requirements

A tab has two buttons A and B. A is selected by default. When B is clicked, the corresponding chart of B needs to be displayed.

Considering that B's chart has been initialized when the page is loaded, the resize method of the chart is called when clicking B.

Since the chart in the tab is written in the child component, the parent component calls the child component method through useImperativeHandle. The React version "react": "^18.1.0", the code is as follows

Parent component:

const childRef = useRef()
const item = [{
        name: 'XXXX',
        content: <RunningRecord cRef={childRef} />,
        handClick: ?.resizeChart
}]
return <>
    ……
    <li onClick={() => {
            setTimeout(() => {
                ('~~',)
                ?.()
            }, 200)
        }}
        key={}>
        {}
    </li>
    ……
    <RunningRecord cRef={childRef} />
</>

Subcomponents:

function RunningRecord({ cRef }) {
    ……
    useImperativeHandle(cRef,()=>({
        resizeChart:()=> {dosomething……}
    }))

question

This is written in the local development mode to run normally, but in the production environment, the parent component cannot get the child component for the first time loading. Tab needs to switch to A and then B.

The reason is guessed that in a production environment, the parent component binds the exposed method of the child component to the click event in the UI, and the child component is initialized late, and the event is not transmitted back after the initial completion.

This guess may not be accurate, please add to those who know it.

Solution

In the parent component, put the process of assigning the child component in useEffect, do not write the dependency parameters (not an empty array without dependencies), and then run, everything is normal.

const usageRecordData = [{
    name: 'XXXX',
    content: <RunningRecord cRef={childRef} />,
}]
useEffect(() => {
    usageRecordData[1].handClick = ?.resizeChart
})

Use useImperativeHandle to let the parent component manipulate the state and methods of the child component

useImperativeHandle is the official react to facilitate our ref operation, and also allows the child component to return to the parent component's own state and method to call it.

useRef binds ref to a subcomponent tag to obtain methods and parameters of the entire subcomponent

  • useImperativeHandle: You can customize methods or variables exposed to parent components

Parent component

import React, { useState, useRef } from 'react'
import ChildList from './ChildList'
export default () =&gt; {
    let parentRef = useRef(null)
    const [name, setName] = useState('li')
    return &lt;div&gt;
        &lt;ChildList parentRef={parentRef} name={name}&gt;&lt;/ChildList&gt;
        &lt;button onClick={() =&gt; {
            ("parentRef", parentRef)
        }}&gt;Get subcomponents&lt;/button&gt;
    &lt;/div&gt;
}

Subcomponents

import React, { useImperativeHandle, forwardRef } from 'react'
export default forwardRef((props, ref) =&gt; {
    ("ref", ref)
    useImperativeHandle(ref, () =&gt; {
        return {
            childFn
        }
    })
    (ref)
    const childFn = () =&gt; {
        ('Subcomponent Method')
    }
    return &lt;div&gt;
        &lt;div ref={ref} /&gt;
    &lt;/div&gt;
})

The bridge using ref can control the child components in the parent component, not just the child rendering with the parent.

The above is personal experience. I hope you can give you a reference and I hope you can support me more.