Search code examples
javascriptreactjsfunctionscrollreturn

Updating image source on scroll using pure javascript


I'm trying to make a component that updates its source image on scroll when it gets referenced in its div tag ' infoBG 'in my main component. The function seems to work but I guess the return statement is overriding the function and just returns the original image without updating. What's the right way to do this so the function updates the first returned image?


function Infoimg () {

  window.addEventListener("scroll", event => {
    var scrollValue = window.scrollY;
    var image = document.getElementById('infoBG');
    if (scrollValue>100){
      image.setAttribute = ('src','images/ccpLogo.svg');
    }else{
      image.setAttribute = ('src','images/Passport Stock Photo.svg');
    }
    console.log(image)
    console.log(scrollValue);
  });
  
 return( 

 <img src={'images/Passport Stock Photo.svg'} alt='Info-Background'/>

 )
  
}


Solution

  • It is generally a bad idea to manipulate the DOM directly in React. Instead, rely on hooks and states to update variables that will be interpolated into your template instead.

    In this case, it makes sense to create a new state using the useState hook to allow reading and writing of your image URL, and then use the setter returned by useState to update the value.

    Moreover, some handful tips:

    1. You should use useEffect() and add the event listener on render
    2. You should also return a function in useEffect() to ensure that your scroll event listener is properly removed to avoid potential memory leaks and allow for garbage collection
    3. You can simplify your if/else statement into a simple ternary statement
    4. You might want to manually invoke onScroll() for the first time, especially if the user may arrive at the page with a cached scroll position (i.e. user does not start from top of page)

    With all these points in mind, here is an improved version of your code:

    const [image, setImage] = useState('images/Passport Stock Photo.svg');
    
    useEffect(() => {
      const onScroll = () => {
        setImage(window.scrollY > 100 ? 'images/ccpLogo.svg' : 'images/Passport Stock Photo.svg');
      };
    
      // Note: Listen to scroll event
      window.addEventListener('scroll', onScroll);
    
      // Optional: Handle scenario where user arrives at a pre-scrolled position (non-zero scrollY on load)
      onScroll();
    
      // Note: Clean up to avoid memory leaks
      return () => {
        window.removeEventListener('scroll', onScroll);
      };
    }, []);
    
    return (
      <img src={image} alt="Info-Background" />
    );