I’m using React with Material-UI and the react-window library’s VariableSizeList component to render a list of dynamically sized components. Each component’s height is determined after it has rendered, so I need a way to calculate and set the height of each component in the VariableSizeList.
Here’s a simplified version of my code:
//@ts-ignore
import React, { useRef, useState, useEffect, useReducer } from 'react';
import { VariableSizeList, ListChildComponentProps } from 'react-window';
import { Box, ListItem, ListItemText } from '@mui/material';
const HistoryList = () => {
const [statComponentHeights, setStatComponentHeights] = useState<number[]>([]);
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
const ListItemComponent = (props: ListChildComponentProps) => {
const licRef = useRef<HTMLDivElement>(null);
// Function to calculate and set height when the component loads
const onLoad = (e: React.SyntheticEvent<HTMLDivElement, Event>) => {
console.log('Client height', e.currentTarget.clientHeight);
const newStatComponentHeightsArray = [...statComponentHeights, e.currentTarget.clientHeight];
setStatComponentHeights(newStatComponentHeightsArray);
}
const listItem = (
<div ref={licRef} style={props.style} onLoad={(e) => onLoad(e)}>
<ListItem sx={{color:'white'}} key={props.index} component="div" disablePadding>
<ListItemText primary={`Item ${props.index}`} />
</ListItem>
</div>
);
return listItem;
};
// Function to return height for each item in VariableSizeList
const getItemSize = (index: number) => {
return statComponentHeights[index] ?? 0; // Right now this returns 0
};
// Force re-render when data changes
useEffect(() => {
// Logic to update state or re-render components when data changes
forceUpdate();
}, [statComponentHeights]);
return (
<Box>
<VariableSizeList
height={400}
width={300}
itemSize={getItemSize}
itemCount={10} // Example itemCount
>
{ListItemComponent}
</VariableSizeList>
</Box>
);
};
export default HistoryList;
My problem is that I need to dynamically calculate and set the height of each component in the VariableSizeList based on their content or other factors that determine their height after they have rendered. I tried using the onLoad event on the div element within each ListItemComponent, but it doesn’t work as expected because the onLoad event is not applicable to div elements.
If you run the code above, you will see that all ten listItems will stack on top of each other because getItemSize() returns 0 since onLoad does not run.
Is there a way to achieve this dynamic height calculation for components in a VariableSizeList with or without the onLoad event? Any suggestions or alternative approaches would be appreciated. Thank you!