'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 |
|---|
