Why is my useState value not updated when it is referenced from inside a function that runs on click

76 Views Asked by At

I have a state value for all the users in the project I am working on, and the state value is updated as I expect it to. The problem is when I try to reference the 'users' state from inside a function, I get the previous value of the state.

I thought it was just because useState updated asynchronously but I am getting the expected value when I reference the 'users' state from other parts of the app. I also tried putting the function inside a useEffect hook that runs every time the 'users' state runs but I still had no luck. The function in question runs with a click event.

const [users, setUsers] = useState([])

  useEffect(() => {
    const subscribe = onSnapshot( usersRef, snap => {
      let tempUsers = []
      snap.docs.forEach(doc => {
        tempUsers.push({ ...doc.data(), id: doc.id })
      })
      setUsers(tempUsers)
    })

    return () => {
      subscribe()
    }
  }, [] )

useEffect(() => { 
    const followBtn = document.querySelector('.follow-btn')
    console.log(users.find(person => person.id === 'uekUbQRcBRYiZpipQGhHUtjwNDA3'))
    console.log(users)
  
    const handleFollow = async () => {
      console.log(users.find(person => person.id === 'uekUbQRcBRYiZpipQGhHUtjwNDA3'))
      console.log(users)
    }

    followBtn.addEventListener('click', handleFollow)

    return () => {
      followBtn.removeEventListener('click', handleFollow)
    }
  }, [users])

the users array in the two above console logs are different, the one outside the function gives the expected value but the one inside the function gives the outdated value, and I am not altering it. The data is being pulled from firebase.

1

There are 1 best solutions below

2
NoNam4 On

You should move your click event logic to your button onClick event:

const [users, setUsers] = useState([])

useEffect(() => {
  const subscribe = onSnapshot( usersRef, snap => {

    setUsers(() => snap.docs.map(doc => {
      return { ...doc.data(), id: doc.id }
    }))
  })

  return () => subscribe()
}, [] )

useEffect(() => { 
  console.log('users changed', users)
  console.log(users.find(person => person.id === 'uekUbQRcBRYiZpipQGhHUtjwNDA3'))
}, [users])

const handleFollow = async () => {
  console.log('button click', users)
  console.log(users.find(person => person.id === 'uekUbQRcBRYiZpipQGhHUtjwNDA3'))
}

return (
  <button 
    onClick={handleFollow}
  >
    click me
  </button>
)