简体   繁体   中英

Weird behavior of React UseEffect with window click eventListener

I'm trying to implement a simple window Click counter. It needs to count clicks on the entire page, not in a single element with like <div onClick={() => handleClick()}></div> .

I have tried many variations of this code:

import React, { useState, useEffect } from 'react';
import $ from 'jquery';

function Test() {
  const [clicks, setClicks] = useState(0);

  function handleClick() {
    try {
      setClicks(() => clicks + 1);
    } catch (err) {
      console.error(err);
    }
  }

  useEffect(() => {
    console.log(clicks);
  }, [clicks]);

  useEffect(() => {
    $(window).on('click', handleClick);
    return () => {
      $(window).off('click', handleClick);
    };
  }, []);

  return (<div>{clicks}</div>);
}

export default Test;

The first useEffect just logs the click state variable every time it changes, so I can see what is happening. The second one adds the event listener and removes it on component unmount. The problem is that it works just fine for the first click. The first useEffect logs 1 and the value inside the <div> changes to 1 . But nothing else happens if I keep clicking. Is this approach wrong?

Thanks!

You have a classical stale closure problem. Use this instead:

  setClicks((clicks) => clicks+ 1);

The way you had it, your clicks would always refer to the value from the first render; it never got updated because you run your useEffect only once.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM