In Piano
component I am getting window's dimensions using a hook (useWindowDimensions()
). In useEffect
, I want to render component everytime width of window changes.
It re-renders the component everytime width changes (because keyData
depends on it and it is in dependencyList
) but does not render in initial render. So component does not render until I resize the window.
Following code is Piano
component.
const svgRef = React.useRef(null);
const svgEl = d3.select(svgRef.current);
const { width } = useWindowDimensions();
const height = width / 4;
const keyData = generateKeyData(88, width);
React.useEffect(() => {
svgEl.selectAll("*").remove();
generatePianoNode(svgEl, keyData);
}, [svgEl, keyData]);
return (
<svg ref={ svgRef } width={ width } height={ height } />
);
I tried to put another useEffect hook with empty dependency list with the same code but it also didn't work.
The useEffect hook actually renders on initial component mount but the problem here is that the way you generate piano node .
You need to somehow put the value in a state and update state so the component re-renders everytime the state changes and also when the component mounts .
const [value , setValue ] = React.useState("1")
React.useEffect(() => {
// your logic
// setValue("2")
}, [value]);
Now the useEffect hook will run on component mount and then everytime the state value changes .
Note
If the value change simultaneously it will cause rendering problem in the component so a better option in this case is assigning an event listener in useEffect like this :
const handleScroll = () => {
// your logic
}
React.useEffect(() => {
if (typeof window !== "undefined"){
window.addEventListener("scroll" , handleScroll)
}
return () => {
// on component unmount remove event listener
if (typeof window !== "undefined"){
window.removeEventListener("scroll" , handleScroll)
}
}
}, []);