I decided to use React hooks for my component using windom width and resize event listener. The problem is that I can't access current value that I need. I get nested value that was set while adding event listener.
Passing function to value setter function is not a solution for me because it's forcing render and breaking my other functionalities.
I am attaching minimalistic example to present core problem:
import React, { Component, useState, useEffect } from 'react';
import { render } from 'react-dom';
const App = () => {
const [width, setWidth] = useState(0);
const resize = () => {
console.log("width:", width); // it's always 0 even after many updates
setWidth(window.innerWidth);
};
useEffect(() => {
resize();
window.addEventListener("resize", resize);
return () => window.removeEventListener("resize", resize);
}, []);
return <div>{width}</div>;
}
render(<App />, document.getElementById('root'));
LIVE DEMO IS HERE
Please for help.
React hooks are not required to return anything.
Don't call Hooks inside loops, conditions, or nested functions. Instead, always use Hooks at the top level of your React function, before any early returns. By following this rule, you ensure that Hooks are called in the same order each time a component renders.
The React useMemo Hook returns a memoized value. Think of memoization as caching a value so that it does not need to be recalculated. The useMemo Hook only runs when one of its dependencies update. This can improve performance.
Every render you get a new copy of resize
function. Each copy captures the current value of width
. Your listener has a copy which was created on the first render with width = 0
.
To fix this issue you have several options:
Update listeners when width
changes
useEffect(() => {
resize();
window.addEventListener("resize", resize);
return () => window.removeEventListener("resize", resize);
}, [width]);
Use functional updates to get the current width inside listener
const resize = () => {
setWidth(oldWidth => {
console.log("width:", oldWidth);
return window.innerWidth
});
};
Store the width in a mutable reference
const widthRef = useRef(width);
const resize = () => {
console.log("width:", widthRef.current);
widthRef.current = window.innerWidth;
setWidth(window.innerWidth);
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With