I am using the useWindowDimensions hook in Get viewport/window height in ReactJS to render the sections inside a component conditionally. This component has got 3 sections, when the width of the browser decreases, there will be fewer sections to be shown.
However, sometimes it spits out the "Warning: Did not expect server HTML to contain the text node "Setup" in ." in the console, and the layout of that page is also messed up. This only happens when the page get refreshed. It doesn't happen when I navigate to this page from another page (i.e. no request is sent to the server).
I would like to know why does this happen only in certain scenarios and how to resolve it in general when a component doesn't behave the same way on the client and the server. It's even better if you could explain how to resolve this particular problem gracefully while preserving the intended behaviour of the page.
Here is the code
// useWindowDimensions.ts
import { useState, useEffect } from "react";
function getWindowDimensions() {
const hasWindow = typeof window !== "undefined";
const width = hasWindow ? window.innerWidth : null;
const height = hasWindow ? window.innerHeight : null;
return {
width,
height,
};
}
const useWindowDimensions = () => {
const [windowDimensions, setWindowDimensions] = useState(
getWindowDimensions()
);
useEffect(() => {
function handleResize() {
setWindowDimensions(getWindowDimensions());
}
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return windowDimensions;
};
export default useWindowDimensions;
// TwoSidesMainSection.tsx
import useWindowDimensions from "../../hooks/useWindowDimensions";
import styles from "./TwoSidesMainSection.module.scss";
type Props = {
leftSection?: React.ReactNode;
mainSection: React.ReactNode;
rightSection?: React.ReactNode;
};
const TwoSidesMainSection: React.FC<Props> = ({
leftSection,
mainSection,
rightSection,
}) => {
const { height, width } = useWindowDimensions();
const shouldDisplayNoSideSection = width < 800;
const shouldDisplayAtMostOneSideSection = width < 1250;
let mainSectionClasses: string = styles.mainSection;
if (!leftSection && !rightSection) {
// only main section is supplied
mainSectionClasses += " " + styles["mainSection-100"];
} else if (!leftSection || !rightSection) {
// either left or right section is supplied
mainSectionClasses += " " + styles["mainSection-75"];
} else {
// both left and right section are supplied
if (shouldDisplayNoSideSection) {
leftSection = null;
rightSection = null;
mainSectionClasses += " " + styles["mainSection-100"];
} else if (shouldDisplayAtMostOneSideSection) {
rightSection = null;
mainSectionClasses += " " + styles["mainSection-75"];
} else {
mainSectionClasses += " " + styles["mainSection-50"];
}
}
return (
<section className={styles.container}>
{!!leftSection && <div className={styles.sideSection}>{leftSection}</div>}
<div id={styles.mainSection} className={mainSectionClasses}>
{mainSection}
</div>
{!!rightSection && (
<div className={styles.sideSection}>{rightSection}</div>
)}
</section>
);
};
export default TwoSidesMainSection;
// SomePage.tsx
const SomePageMainSection = () => {
return (
<Fragment>
<Title>Setup</Title>
</Fragment>
);
}
const SomePage = () => {
return (
<TwoSidesMainSection
leftSection={<div></div>}
mainSection={<SomePageSection />}
rightSection={<div></div>}
/>
);
};
export default SomePage;