似乎无法通过空依赖数组影响 React 的 useEffect() 中的状态。套接字.io

Posted

技术标签:

【中文标题】似乎无法通过空依赖数组影响 React 的 useEffect() 中的状态。套接字.io【英文标题】:Can't seem to affect state from within React's useEffect() with empty dependencies array. Socket.io 【发布时间】:2020-11-29 12:54:57 【问题描述】:

基本上我认为我的问题是为什么我不能在 useEffect 中从我的状态访问 allUserMessages 而它的依赖数组中没有任何内容?更多细节如下。谢谢。

我正在尝试使用 componentDidMount 之类的 useeffect 推送到我状态下的数组,以获取传入的 websockets 数据。但是当消息进来时,它似乎会推送最新的消息,但不会保留数组的其余部分,因为在我的聊天日志中,我只收到发送的最新消息,而不是所有消息的日志。当我在我的 useeffect 函数中取出空的依赖项数组时,它可以推送到数组并拥有完整的聊天日志,但它似乎会递归地接收我数组中的每条消息的消息,所以到第 5 条或第 6 条消息时,应用程序变为非常慢 它控制台多次记录相同的消息,并随着每条消息的增加而增加。如果您不介意,请查看我的代码,如果您有任何想法,请告诉我。我真的很感激。

const socket = io.connect()

const Community = () => 
 const [userMessage, setUserMessage] = useState("");
 const [allUserMessages, setUserMessages] = useState([])
 const [showMentions, setShowMentions] = useState(false)
 const [activeUsersForMentions, setActiveUsersForMentions] = useState([])
 const [mentionIDs, setMentionIDs] = useState([])
 const [userID, setUserID] = useState()

 useEffect(()=>

 socket.on("incomingMessage", (data) => 
    console.log(data);

    socket.emit("joinRoom", roomid: 'lounge')
    console.log('joining room');

    //get the current list of all messages on the channel
    //push the new message with the info from data
    let isUserMentioned = false;
    if(typeof data.mentions.find(x=>x === userID) != 'undefined')
        isUserMentioned = true;
    

    console.log(allUserMessages);
    
    //set state again with modified array to include the new message
    setUserMessages([...allUserMessages, first_name: data.first_name,
      last_name: data.last_name,
      avatar: data.avatar,
      message: data.message,
      account_type:data.account_type,
      isMentioned: isUserMentioned])
  )
 ,[])



【问题讨论】:

【参考方案1】:

因为依赖项数组是空的,所以在您的回调中,您保证allUserMessages 将是[](它的初始状态),因为您的回调关闭了该初始状态并且是仅在最初创建组件后调用一次。但是即使在更新状态之后,您也会反复从套接字获取消息。

要修复它,请使用回调版本的setUserMessages

setUserMessages(allUserMessages => [...allUserMessages, first_name: data.first_name,
// −−−−−−−−−−−−−^^^^^^^^^^^^^^^^^^
    last_name: data.last_name,
    avatar: data.avatar,
    message: data.message,
    account_type:data.account_type,
    isMentioned: isUserMentioned
]);

这样,您将始终获得allUserMessages 的最新版本,而不仅仅是首次创建组件时的最新版本。

一般来说,在 React 中,如果您基于现有状态项更新状态项,则 99% 的时间您都希望使用状态设置器的回调版本,以便始终拥有最新的-日期状态。


¹它确实应该被称为setAllUserMessages(或者状态项应该是userMessages而不是allUserMessages),因为状态项是allUserMessages。这只是惯例,但却是压倒性的普遍惯例。

【讨论】:

谢谢!我把头发拉了很长时间,你明白了。我很感激,我只需要这样做并将 setAllUserMessages 放入依赖数组中就可以了。谢谢T.J @CharlesPettis - 乐于助人!您永远不需要将状态设置器放入依赖数组中。 React 保证它们永远不会改变。最好将其排除在外,这样很明显这是一次性效果。【参考方案2】:

现在,因为您有一个空的依赖项数组,所以您的 useEffect 挂钩仅在您加载组件时运行一次。如果你完全删除了依赖数组,你的 useEffect 将无限期地继续运行。您需要在数组中设置适当的依赖项,这将使您的 useEffect 挂钩在每次该值更改时运行。

【讨论】:

当我将我的聊天日志数组 (allUserMessages) 放入依赖项时,它会在我的控制台中一遍又一遍地循环接收消息,每条消息都会越来越多,直到它崩溃我的浏览器 不,OP不需要设置任何其他依赖;这将导致对套接字的冗余订阅。他们只需要使用最新版本的allUserMessages

以上是关于似乎无法通过空依赖数组影响 React 的 useEffect() 中的状态。套接字.io的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 React 中的嵌套对象数组进行映射

无法在 React 状态下设置对象数组

无法使用 React Native 和 Axios 发送请求

using 指令如何影响 C++ 中的函数参数?

react-native run-android无法在空对象上获取属性'packageName'

Mongoose Populate Child ref 返回空数组