【问题标题】:Socket listener not getting updates from React state套接字侦听器未从 React 状态获取更新
【发布时间】:2021-08-06 16:10:54
【问题描述】:

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

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 更改时您似乎没有清除以前的侦听器,因此可能同时添加了多个侦听器 - 每个侦听器都有不同版本的 activeList 数组。能否将console.log 添加到监听器的主体中,并检查过滤后它会被调用多少次?
  • @Aitwar 在套接字侦听器中添加了一个 console.log - 它只按预期被调用一次

标签: javascript reactjs socket.io


【解决方案1】:

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

所以,请尝试使用returnuseEffect

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

  socket.on('notification', handler);

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

此外,当您只想更新 activeList 时,setter 函数会获取以前的值,因此您可以直接使用它,然后您的效果不需要任何 dep,除了对 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]);

【讨论】:

  • 谢谢!这很好用。我遇到的一件事是在设置新值后 DOM 没有更新。所以我将 prev 复制到一个新值“copy”并返回 - 现在一切正常。
猜你喜欢
  • 2021-05-10
  • 2023-01-07
  • 2019-05-19
  • 2017-09-03
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多