Search code examples
reactjslaravelpusherlaravel-echo

React state is empty inside useEffect


Currently I'm building a pusher chat app with react. I'm trying to keep a list of online users. I'm using this code below:

const [users, setUsers] = useState([]);
useEffect(() => { // UseEffect so only called at first time render
window.Echo.join("server.0")
  .here((allUsers) => {
    let addUsers = [];
    allUsers.map((u) => {
      addUsers.push(u.name)
    })
    setUsers(addUsers);
  })
  .joining((user) => {
    console.log(`User ${user.name} joined`);
    setUsers([users, user]);
  })
  .leaving((user) => {
    console.log(`User ${user.name} left`);
    let addUsers = users;
    addUsers.filter((u) => {
      return u !== user.name;
    })
    setUsers(addUsers);
  })}, []);

Whenever I subscribe to the pusher channel, I receive the users that are currently subscribed and the state is set correctly. All subscribed users are showing. However when a new user joins/leaves, the .joining/.leaving method is called and the users state is empty when I console log it. This way the users state is being set to only the newly added user and all other users are being ignored. I'm new to react so there is probably a simple explanation for this. I was not able to find the answer myself tough. I would really appreciate your help.


Solution

  • I found the issue. The problem is that when accessing state from within a callback funtion, it always returns the initial value. In my case an empty array. It does work when using a reference variable. I added the following lines:

      const [users, _setUsers] = useState([]);
      const usersRef = React.useRef(users);
      const setUsers = data => {
       usersRef.current = data;
      _setUsers(data);
       }
    

    Each time I update the users state, I use the setUsers function. Now when I acces the state from inside my callback function with usersRef.current I get the latest state.

    Also I used the code from the answer of @Viet to update the values correctly.