Search code examples
reactjsreact-hooksuse-effect

useEffect does not run in initial render


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.


Solution

  • 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)
         } 
      }
    }, []);