简体   繁体   中英

React.js State not updating in Event Listener in useEffect Hook

So, What I'm trying to do is add an event listener to a button that when pressed takes the value of a state and console log it. But the logged value never updates even after the multiple setState calls.

    useEffect(() => {
      const seamCarve = document.getElementById("process");
    
      seamCarve.addEventListener("click", (e) => {
        console.log(seamValue);
      });
    }, []);

And then there's the button that triggers it

          <div id="seamvalue">
            <Typography variant="h6" align="center">
              Seams Reduction:<span id="valueOfSeam"> {seamValue} </span>
            </Typography>
          </div>
    
          <Button
            id="leftslider"
            variant="contained"
            color="primary"
            onClick={() =>
              seamValue - 10 > 0 ? setSeamValue(seamValue - 10) : setSeamValue(0)
            }
          >
            <Typography>{"<"}</Typography>
          </Button>
    
          <Button
            id="rightslider"
            variant="contained"
            color="primary"
            onClick={() => setSeamValue(seamValue + 10)}
          >
            <Typography>{">"}</Typography>
          </Button>
    
          <Button id="process" variant="contained" color="primary">
            <Typography>Carve</Typography>
          </Button>

The value changes as I click on the sliders but when I press the Button with id="process" with an event listener associated with it, it only prints 20 even after updating the state.

Don't use native DOM methods like addEventListener in React if at all possible - instead, work within React to achieve the same effect. It'll make a whole lot more sense and will require less convoluted code.

Put the click listener in the JSX syntax returned instead.

<Button
    id="process"
    variant="contained"
    color="primary"
    onClick={() => console.log(seamValue)}
>
    <Typography>Carve</Typography>
</Button>

If you absolutely cannot attach the click listener via React for some reason, then attach the listener again when the state changes. Also note that in order to start a function, you need a { after the => , unless you're using concise return (which you aren't here).

useEffect(() => {
    const seamCarve = document.getElementById("process");
    const handler = () => {
        console.log(seamValue);
    };
    seamCarve.addEventListener('click', handler);
    return () => seamCarve.removeEventListener('click', handler);
}, [seamValue]);

State variables don't update itself inside an EventListener. If you want to update and access some state inside an EventListener, look into useRef . Also, you need to replace your 2nd useState statement with useEffect since that's what you wanted to implement. A relevant post that should answer your question: Wrong React hooks behaviour with event listener

EDIT: as @CertainPerformance stated, event listeners like onClick can be directly used inside the jsx. My answer applies to the use of event listeners on the document .

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