When running the below code that gets the screen width of the browser I get this error:
ReferenceError: window is not defined
The code commented-out works, uses 0 as a default, but correctly updates when the browser width is changed.
I either get the window is not defined error or pass a default number to state, which displays the incorrect width on page load.
How do I define window.innerWidth at page load?
import React, { useState, useEffect } from "react";
const WindowTracker = () => {
const [show, setShow] = useState(true);
// const [windowWidth, setWindowWidth] = useState(0);
const [windowWidth, setWindowWidth] = useState(window.innerWidth);
const triggerToggle = () => {
setShow(!show);
};
useEffect(() => {
function watchWidth() {
setWindowWidth(window.innerWidth);
}
window.addEventListener("resize", watchWidth);
return function () {
window.removeEventListener("resize", watchWidth);
};
}, []);
return (
<div>
<button onClick={triggerToggle}>Toggle WindowTracker</button>
{show && <h1>Window width: {windowWidth}px</h1>}
</div>
);
// }
};
export default WindowTracker;
Thanks!
CodePudding user response:
Use this Hook :
const [windowWidth, setWindowWidth] = useState();
useEffect(() => {
setWindowWidth(window.innerWidth)
}, [window.innerWidth])
CodePudding user response:
This happens because in the pre rendering that nextjs performs on the window server it is not yet defined, I solved this in my code by adding an if, this is an example code of how it would look
import React, { useState, useEffect } from "react";
const WindowTracker = () => {
const [show, setShow] = useState(true);
// const [windowWidth, setWindowWidth] = useState(0);
const [windowWidth, setWindowWidth] = useState(typeof window !== "undefined" ? window.innerWidth : 0);
const triggerToggle = () => {
setShow(!show);
};
useEffect(() => {
if (typeof window !== "undefined") {
function watchWidth() {
setWindowWidth(window.innerWidth);
}
window.addEventListener("resize", watchWidth);
return function () {
window.removeEventListener("resize", watchWidth);
};
}
}, []);
return (
<div>
<button onClick={triggerToggle}>Toggle WindowTracker</button>
{show && <h1>Window width: {windowWidth}px</h1>}
</div>
);
// }
};
export default WindowTracker;
CodePudding user response:
You should trigger setWindowWidth
when component did mount
const isClientSide = () => typeof window !== 'undefined';
const getWindowSize = () => {
if (isClientSide()) return window.innerWidth
return 0
}
const WindowTracker = () => {
const [show, setShow] = useState(true);
const [windowWidth, setWindowWidth] = useState(getWindowSize());
const triggerToggle = () => {
setShow(!show);
};
useEffect(() => {
function watchWidth() {
setWindowWidth(window.innerWidth);
}
window.addEventListener("resize", watchWidth);
setWindowSize(getWindowSize()); <=== This should set the right width
return function () {
window.removeEventListener("resize", watchWidth);
};
}, []);
return (
<div>
<button onClick={triggerToggle}>Toggle WindowTracker</button>
{show && <h1>Window width: {windowWidth}px</h1>}
</div>
);
};
export default WindowTracker;
CodePudding user response:
Inside useEffect
hook you can also invoke setWindowWidth(window.innerWidth);
at to set the state with window.innerWidth to have desired width on pageLoad.
const [windowWidth, setWindowWidth] = useState(0);
useEffect(() => {
function watchWidth() {
setWindowWidth(window.innerWidth);
}
window.addEventListener("resize", watchWidth);
// Call right away so state gets updated with initial window size
setWindowWidth(window.innerWidth);
return function () {
window.removeEventListener("resize", watchWidth);
};
}, []);