1

Switching over to react hooks and using them for the first time. My state always seems to be set back to the initial value I pass it (0). Code is to have a page automatically scroll down and up. The page is just practice to displaying various file types. What happens is the scrollDir variable will switch to being set to either 1 or -1 and 0. So the console will display 1,0,1,0,1,0,1,0 etc... How do I get the state to stay during an update?

function App(props) {

  const [scrollDir, setScrollDir] = useState(0);

  function scrollDown() {
    if(document.documentElement.scrollTop < 10)
    {
      setScrollDir(1);
    }
    else if(document.documentElement.scrollTop >= document.documentElement.scrollHeight - window.innerHeight)
    {
      setScrollDir(-1);
    }

    window.scrollBy(0, scrollDir);
  }

  useEffect(() => {
    setInterval(scrollDown, 100);
  });

  return (
    <StackGrid monitorImagesLoaded={true} columnWidth={"33.33%"} >
      <img src={posterPNG} />
      <img src={posterJPG} />
      <img src={posterGIF} />
      <video src={posterMP4} loop autoPlay muted />
      <Document file={posterPDF}>
        <Page pageNumber={1} />
      </Document>
    </StackGrid>
  );
}
Grant Kochmann
  • 159
  • 1
  • 3
  • 14
  • 1
    Using `setInterval` with hooks isn't very intuitive. See here for an example: https://stackoverflow.com/a/53990887/3984987. For a more in-depth explanation you can read this https://overreacted.io/making-setinterval-declarative-with-react-hooks/ – DonovanM May 07 '19 at 21:26
  • You need to clearInterval in the hook cleanup return function – Andy Ray May 07 '19 at 21:29
  • @DonovanM Nice I used the references you attached to figure it out. Interesting stuff! I like this answer because it introduced me to custom hooks as well. If you type it up as an answer I'll accept it. – Grant Kochmann May 08 '19 at 02:33
  • @GrantKochmann Yeah, custom hooks are really useful! Thanks, I added my previous comment as an answer. – DonovanM May 08 '19 at 02:38

2 Answers2

2

useEffect hook takes second argument, an array. If some value in that array changes then useEffect hook will run again

If you leave that array empty useEfect will run only when component mount - (basicaly like ComponentDidMount lifecycle method)

And if you omit that array useEffect will run every time component rerenders

For example:

useEffect runs only once, when component mounts:

useEffect(() => {
 //code 
},[]);

useEffect runs everytime when component rerenders:

useEffect(() => {
 //code 
});

useEffect runs only when some of these variables changes:

let a = 1;
let b = 2;
    useEffect(() => {
     //code 
    },[a,b]);

Also, if you set return statement in useEffect hook, it has to return a function, and that function will always run before useEffect render

  useEffect(() => {
    // code
    return () => {
      console.log("You will se this before useEffect hook render");
    };
  }, []);
JozeV
  • 616
  • 3
  • 14
  • 27
1

Using setInterval with hooks isn't very intuitive. See here for an example: https://stackoverflow.com/a/53990887/3984987. For a more in-depth explanation you can read this https://overreacted.io/making-setinterval-declarative-with-react-hooks.

This useInterval custom hook is pretty easy to use as well https://github.com/donavon/use-interval. (It's not mine - I ran across this after responding earlier)

DonovanM
  • 1,174
  • 1
  • 12
  • 17