Reputation: 1129
I'm trying to create a ReactJS (using react bootstrap) mobile app that can resize (expand or contract) itself based on the screensize. The dimensions of one part of the app need to be calculated based on how much space is left on the screen after all other parts have rendered.
For example, consider the below markup -
var calcWidth = (100 / tableSize).toString() + '%';
return(
<Container>
<Row id='1'>Header and other static stuff here</Row>
<Row id='2'>
//A db driven table with square shaped cells goes here. It has the below structure -
<Container style={{width:'100%'}}>
<Row><Col style={{width:calcWidth, paddingBottom:calcWidth}}></Col>...</Row>
...
</Container>
</Row>
<Row id='3'>Footer and other static stuff here</Row>
</Container>
);
In the above markup, Row id 1 and 3 contain static stuff like headers, footers, buttons, titles etc. The Row id 2 contains a table that can contain "n" number of cells and each cell needs to be square shaped with content horizontally and vertically centerd.
The above code correctly calculates the width of each cell from the width of the container (which is 100%) and creates square shaped cells and fits perfectly horizontally. But since the height is same as the width, it gets bigger vertically and drives the footer beyond the screen. We want to avoid scrollbars. The solution seems to be to calculate calcWidth
based on the remaining height available to the table, something like the below -
var remainingHeight = <total height of the container> - <height taken up by Row 1> - <height taken up by Row 3>
var width = <width of the screen>
var calcWidth = ((remainingHeight < width ? remainingHeight : width) / tableSize).toString() + '%';
My questions are -
Upvotes: 0
Views: 40
Reputation: 11456
Here you can find an example on how to calculate the height of react components after rendering:
export default function App() {
const [height1, setHeigt1] = useState(0);
const [height2, setHeight2] = useState(0);
const [height3, setHeight3] = useState(0);
const [remainingHeight, setRemainingHeight] = useState(0);
useEffect(() => {
const remainingHeight = 100 - height1 - height2 - height3;
console.log(remainingHeight);
setRemainingHeight(remainingHeight);
}, [setRemainingHeight, height1, height2, height3]);
return (
<div
id="container"
style={{
height: "100px",
backgroundColor: "firebrick",
padding: "15px"
}}
>
<ResizableComponent
id="component-1"
content={`Initial component 1 height = ${height1}`}
onHeightUpdated={setHeigt1}
/>
<ResizableComponent
id="component-2"
content={`Initial component 2 height = ${height2}`}
onHeightUpdated={setHeight2}
/>
<ResizableComponent
id="component-3"
content={`Initial component 3 height = ${height3}`}
onHeightUpdated={setHeight3}
remainingHeight={remainingHeight}
/>
</div>
);
}
export function ResizableComponent({
id,
content,
onHeightUpdated,
remainingHeight
}) {
const [height, setHeight] = useState(0);
const [isFirstRender, setIsFirstRender] = useState(true);
useEffect(() => {
const newHeight = document.getElementById(id).clientHeight;
if (height !== newHeight && isFirstRender) {
setHeight(newHeight);
setIsFirstRender(false);
}
}, [isFirstRender, id, height, onHeightUpdated, remainingHeight]);
useEffect(() => {
onHeightUpdated(height);
}, [height, onHeightUpdated]);
return (
<div
id={id}
style={
remainingHeight
? {
backgroundColor: "pink",
height: `calc(${height}px + ${remainingHeight}px)`
}
: { backgroundColor: "pink" }
}
>
{content}
</div>
);
}
Upvotes: 1