0

I'm trying to use my useScrollPosition() hooks in my main app. It's used to adjust the container's height depending on the scroll position.

Problem: When I scroll down, the useScrollPosition() isnt being called.

Here's the working example: https://codesandbox.io/s/recursing-khorana-5yffl?file=/src/App.js

Please help me get my useScrollPosition() hook to work again. I have a feeling it is due to my fixed position styling, or the way I'm calling the eventListener.

My code:

import React, { useEffect, useState } from "react";

const useWindowSize = () => {
  const [windowSize, setWindowSize] = useState({
    width: undefined,
    height: undefined
  });

  useEffect(() => {
    function handleResize() {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight
      });
    }
    window.addEventListener("resize", handleResize);
    handleResize();
    return () => window.removeEventListener("resize", handleResize);
  }, []);
  return windowSize;
};
const useScrollPosition = () => { // error is probably here
  const [position, setPosition] = useState({
    x: window.scrollX,
    y: window.scrollY
  });
  useEffect(() => {
    const handleScroll = () => {
      console.log("test");

      setPosition({
        x: window.scrollX,
        y: window.scrollY
      });
    };
    window.addEventListener("scroll", handleScroll);
    handleScroll();
    return () => window.removeEventListener("scroll", handleScroll);
  }, []);
  return position;
};

const appContainerStyle = {
  position: "fixed",
  height: "100%",
  width: "100%",
  display: "flex",
  justifyContent: "center",
  alignItems: "flex-end",
  backgroundColor: "black",
  overflowY: "scroll"
};

export default function App() {
  const size = useWindowSize();
  const position = useScrollPosition();

  const containerStyle = {
    position: "relative",
    height: size.width <= 1024 && size.height <= 1366 ? "100%" : "50%",
    width: "100%"
  };
  const contentContainerStyle = {
    height: position.y <= size.height / 10 ? "90%" : "100%",
    width: "100%"
  };
  const navContainerStyle = {
    position: "fixed",
    height: position.y <= size.height / 10 ? "10%" : "0%",
    width: "100%",
    backgroundColor: "rgba(0,0,0,.5)",
    zIndex: "1",
    top: "0"
  };
  console.log(position.y, size.height / 10);
  return (
    <div style={appContainerStyle}>
      <div style={navContainerStyle}></div>
      <div style={contentContainerStyle}>
        <div style={{ ...containerStyle, backgroundColor: "red" }}></div>
        <div style={{ ...containerStyle, backgroundColor: "green" }}></div>
        <div style={{ ...containerStyle, backgroundColor: "blue" }}></div>
        <div style={{ ...containerStyle, backgroundColor: "orange" }}></div>
        <div style={{ ...containerStyle, backgroundColor: "purple" }}></div>
      </div>
    </div>
  );
}

1 Answer 1

0

You are not scrolling inside the window, but inside the appContainer.

You need to add the event listener to the appContainer. That can be done with a ref:

    const myScrollBox = useRef(null);
    const position = useScrollPosition( myScrollBox.current );
// ...
        <div id="mainContainer" style={ appContainerStyle } ref={ myScrollBox }>

Inside useScrollPosition you need to make sure the component has been rendered already:

const useScrollPosition = ( elementRef ) => { // <-- pass the element ref
    const [ position, setPosition ] = useState({ x: 0, y: 0 });
    const [ element, setElement ] = useState(null);

    // -- set DOM element, if ref is ready and element is not set already
    useEffect(() =>{
        if( elementRef && !element ){
            setElement( elementRef );
        }
    });

    useEffect(() => {

        if( !element ){ return; }      // <-- skip if element is not ready

        const handleScroll = () => {
            setPosition({
                x: element.scrollTop,  // <-- .scrollTop instead of .scrollY
                y: element.scrollLeft  // <-- .scrollLeft instead of .scrollX
            });
        };

        element.addEventListener("scroll", handleScroll);
 
        return () => { element.removeEventListener('scroll', handleScroll); };
    }, [ element ]);            // <-- add element to dependencies

    return position;
};
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.