-1

im trying to use and learn the useState hook. i have an event listner for onclick events. when the events start i just want to update the clickcount with setState. made a section where the user can type:typing section, i dont want for the use effect to be depended on the event. i want to take a dom item in correlation to the amount of keys pressed

const [clickCounter, setClickCounter] = useState(1)
const [initialRender, setInitalRender] = useState(true)
 useEffect(() => {
    const typingSection = document.querySelector(".typing-section")

    if (initialRender) {
        typingSection.addEventListener("keypress", keyPressed)
        typingSection.addEventListener("keyup", keyReleased)
        setInitalRender(false)
    }

    return () => {
        document.removeEventListener("keypress", keyPressed)
    }
})
 const keyPressed = (e) => {
    e.preventDefault()
    setClickCounter(clickCounter + 1)
    console.log(e.key,clickCounter)
}
  • Does this answer your question? [The useState set method is not reflecting a change immediately](https://stackoverflow.com/questions/54069253/the-usestate-set-method-is-not-reflecting-a-change-immediately) – jonrsharpe Oct 24 '22 at 10:54
  • Also likely relevant: https://reactjs.org/docs/hooks-reference.html#functional-updates – jonrsharpe Oct 24 '22 at 10:54
  • @nehoray genis Did my answer help you? – Valentin Oct 27 '22 at 08:04

1 Answers1

0

There is a combination of issues here:

  1. Your useEffect has no dependencies declared so it is run on every render of this component.

  2. You tried to protect against this by using initialRender but you didn't put the cleanup function in the if block so the event listener gets cleaned up right on the second render (or on the first one if you are using <React.Strict> in development mode).

  3. The keyPressed function captures the value of clickCounter (it will not change after because of point 2).

This would be my suggestion to fix your issues:

const [clickCounter, setClickCounter] = useState(1)
useEffect(() => {
    const keyPressed = (e) => {
        e.preventDefault()
        // Use the setState updater form so that keyPressed doesn't need to be updated when clickCounter value changes
        setClickCounter(clickCount => {
            console.log(e.key, clickCount)
            return clickCount + 1
        })
    }
    const typingSection = document.querySelector(".typing-section")

    typingSection.addEventListener("keypress", keyPressed)
    typingSection.addEventListener("keyup", keyReleased)
    
    return () => {
        document.removeEventListener("keypress", keyPressed)
    }
}, [setClickCounter]) // You need to specify useEffect dependencies
Valentin
  • 10,769
  • 2
  • 17
  • 27