套接字侦听器未从 React 状态获取更新

Socket listener not getting updates from React state

我有一个组件,我在其中将我的状态从传递的参数设置到组件

function ChatList({ bookingList, session, setActiveChat, setBookingList, socket }){

const [activeList, setActiveList] = useState(bookingList);
const [defaultList, setDefaultList] = useState(bookingList);

我根据传递的参数设置 activeList 状态,然后在单击时更新状态以显示筛选结果

    const changeTab = (index) => {
    if(index === 0){
        setActiveList(defaultList);
        if(defaultList.length > 0){
            setActiveChat(defaultList[0]);
        }else{
            setActiveChat(null);
        }
    }else {  
        let result = bookingList.filter(booking => booking.is_service_provider == false);
        setActiveList(result);
        if(result.length > 0){
            setActiveChat(result[0]);
        }else{
            setActiveChat(null);
        }
    }

因此最终用户可以根据所选索引过滤他们的聊天列表

一切正常,DOM 已更新,如果我从常规函数调用状态,它会显示正确的状态。

但是当我尝试从套接字侦听器更新状态时,我得到的是原始状态而不是过滤后的状态

    useEffect(() => {
    socket.on('notification', (payload) => {

        let list_index = activeList.findIndex(obj => obj.id === payload.room);

        if(list_index > -1){
            let copy = [...activeList];
            copy[list_index].latest_message = payload.message;
            setActiveList(copy);
        }else{
            //Handle if user isnt in the correct segment
        }
            
    });
},[activeList])

这里的问题是 activeList 在过滤后应该只有 2 个元素,但在套接字侦听器中,它获得了 activeList 以及过滤前的所有元素。

我什至用随机的 onclick 侦听器对此进行了测试,onclick 函数获得了正确的状态,那么为什么我的套接字侦听器没有获得更新的状态?

谢谢

每当 activeList 更改时,您都会添加一个侦听器,但不会删除以前的处理程序。它可能会引起你的注意

所以,尝试使用 useEffectreturn

useEffect(() => {
  function handler(payload) {....}

  socket.on('notification', handler);

  return () => socket.off('notification', handler);
}, [activeList]);

此外,当您只想更新 activeList 时,setter 函数会获取以前的值,因此您可以直接使用它,然后您的效果将不需要任何依赖,除了参考 setter 函数。

useEffect(() => {
  function handler(payload) {
    ...
    setActiveList((prev) => {
       const index = prev.findIndex(obj => obj.id === payload.room);
       if (...) return [];
       
       return [];
    });

  }

  socket.on('notification', handler);

  return () => socket.off('notification', handler);
}, [setActiveList]);