'Should I use useImperativeHandle hook when needing multiple refs

I am building component(ThePieChart) where I need to perform quite a bit of DOM manipulation on its elements. Those manipulations I need to perform in parent component(ContinentsInfo) so I used "forwardRef" so I can pass from parent component ref and attach it to child component elements. But I found myself needing multiple refs from child component so I decided to "box" all those refs in one ref object and pass that object.

const ContinentsInfo = () => {

    const pieSlicesRefs = useRef([])    //ARRAY OF REFS OF PIE SLICES FROM PIE-CHART COMPONENT
    const tooltipRef = useRef()    //REF OF PIE CHART TOOLTIP
    const pieChartRef = useRef({pieSlicesRefs, tooltipRef}) // BOX OF REFS

    
    const handleMouseOver = (continent) => {
        //...
    }


    const handleMouseOut = (continent) => {
        //...
    }


    const data = useAsyncIO({sideEffectFunction: getContinentsData})
    const loaderOrLegend = isNil(data) ? <Loading /> :  data.map(x => <ContinentLegend key={x.continent} continent={x.continent} totalCases={x.cases} onMouseOver={handleMouseOver} onMouseOut={handleMouseOut}/>)

    return (
      <>
          <div className={styles['continental__legends']} >
                {loaderOrLegend}
          </div>
          <ThePieChart ref={pieChartRef}/>
      </>
    )

}

export default ContinentsInfo;

Inside of child component(ThePieChart) I use destructuring of those refs and assigning them to elements:

function ThePieChart(props, ref){

    const {pieSlicesRefs, tooltipRef} = ref.current;
    
    let width = 600
    let height = 600
    let margin = 20

    let radius = Math.min(width, height) / 2 - margin;

    const colors = ['#ffd384','#94ebcd','#fbaccc','#1a78be','#fa7f72', '#5033ec']

    const data = [
        {continent: 'Africa', infected: 8790143},
        {continent: 'Europe', infected: 215424950},
        {continent: 'North America', infected: 153251277},
        {continent: 'South America', infected: 54913452},
        {continent: 'Asia', infected: 57882962},
        {continent: "Australia-Oceania", infected: 21702163}
    ];

    const pie = d3.pie().value(function(d) {
        return d.infected;
    })(data);

    const ordScale = d3.scaleOrdinal()
        .domain(data)
        .range(colors);


    const arc = d3.arc()
        .outerRadius(radius)
        .innerRadius(0);

    return (
        <div  className={styles.canvas__wrapper}>
            <div className={styles.canvas}>
                <svg viewBox={`0 0 ${width} ${height}`} overflow={'visible'}>
                    <g transform={`translate(${width / 2}, ${height / 2})`}>
                        {pie.map( (x, i) => {
                            const sliceColor = ordScale(x.data.continent);
                            return <path ref={el => pieSlicesRefs.current[i] = el} key={x.data.continent} d={arc(x)} id={`${x.data.continent}`} fill={sliceColor} data-color={sliceColor} className={styles['piechart__path']} />
                        })}
                    </g>
                </svg>

                <div ref={tooltipRef} className="piechart__tooltip hidden">
                    <h4>N. America</h4>
                    <p>5K Infected</p>
                </div>
            </div>
        </div>
    )
}

export default React.forwardRef(ThePieChart);

My question is should I use "useImperativeHandle" hook and expose DOM manipulation functions from the component itself?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source