0

So I have this code here below. I just want to move this sticky button to the right or to any different different position on screen when I do scroll down. I already ask some friend and you cannot use onScroll or something similar on React, you have to create document-on-scroll-something I believe, I am stuck, and I need help. Again, here's my code below.

App.js

import React from "react";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <ScrollTest />
    </div>
  );
}

class ScrollTest extends React.Component {
  render() {
    return (
      <div id="myScroll">
        <button className="myButton">Click Me</button>
        <h3>Title</h3>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </p>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </p>
      </div>
    );
  }
}


style.css

.App {
  font-family: sans-serif;
  text-align: justify;
}

#myScroll .myButton {
  position: sticky;
  top: 0;
}

index.js

import React from "react";
import ReactDOM from "react-dom";

import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  rootElement
);

Or you can visit my live code here

Thanks a lot

EDIT: typo, supposed onScroll not onScreen

AtomicCommit
  • 39
  • 1
  • 7

1 Answers1

1

I am confused why you couldn't use onScroll to do this.

To break down what is being done:

  • Setup the scrollListener variable with useRef
   const scrollListener = React.useRef();
  • Set that up to watch your scrollable div along with an onScroll event:
<div onScroll={() => onScroll()} ref={scrollListener}>
   [SCROLLABLE CONTENT]
</div>
  • Now you need to implement the onScroll function, which is where you would use a state to control whatever it is you need to control on your DOM.

For this case I am just checking for when you reach 85% of the height of your div through scrolling down and I just set the reachedBottom flag when I reach that point. I later use that information to pull the button to the right which is what you mentioned you wanted to do.

const onScroll = () => { 
        if (scrollListener.current) {
          const { scrollTop, scrollHeight, clientHeight } = scrollListener.current;

          if (scrollTop + clientHeight >= scrollHeight * 0.85) {
            if (!reachedBottom) {
              setReachedBottom(true);
            }
          } else {
            if (reachedBottom) {
              setReachedBottom(false);
            }
          }
        }
      };

Here is a sample app very similar to yours where I do what it sounds like you are describing.

const App = () => {
    const scrollListener = React.useRef();
    const [reachedBottom, setReachedBottom] = React.useState(false);
    
const onScroll = () => {
    if (scrollListener.current) {
      const { scrollTop, scrollHeight, clientHeight } = scrollListener.current;

      if (scrollTop + clientHeight >= scrollHeight * 0.85) {
        if (!reachedBottom) {
          setReachedBottom(true);
        }
      } else {
        if (reachedBottom) {
          setReachedBottom(false);
        }
      }
    }
  };

  return (
  <div className='myScroll' >
   <button className="myButton" style={{float: reachedBottom ? 'right' : ''}}>Click Me</button>
      <div className="main" onScroll={() => onScroll()} ref={scrollListener}>
       
        <h3>Title</h3>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </p>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </p>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </p>
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
          eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
          minim veniam, quis nostrud exercitation ullamco laboris nisi ut
          aliquip ex ea commodo consequat. Duis aute irure dolor in
          reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
          pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
          culpa qui officia deserunt mollit anim id est laborum.
        </p>
      </div>
  </div>
  )
}

ReactDOM.render(
    <App />,
    document.getElementById('app')
);
    .App {
      font-family: sans-serif;
      text-align: justify;
    }

    #myScroll .myButton {
      position: sticky;
      top: 0;
    }

    .main {
      position: relative;
      height: 300px;
      overflow-y: scroll;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
    <div id="app"></div>
theJuls
  • 6,788
  • 14
  • 73
  • 160
  • I see that you use useRef, its a hook or for Functional Component right? I assume it is componentDidUpdate or something on class component. – AtomicCommit Jan 15 '21 at 03:01
  • [useRef](https://reactjs.org/docs/hooks-reference.html#useref) is indeed a hook for a functional component. However, the one you are thinking of is [useEffect](https://reactjs.org/docs/hooks-reference.html#useeffect). If I remember correctly, useRef in a class component is something like `createRef`, don't remember the details though. – theJuls Jan 15 '21 at 03:18
  • Indeed the class based version of it is [createRef](https://stackoverflow.com/questions/62499061/how-to-use-react-useref-in-class-component) – theJuls Jan 15 '21 at 03:20