使用空的依赖项数组似乎无法影响 React 的 useEffect() 中的状态。Socket.io

Cha*_*tis 4 javascript websocket node.js socket.io reactjs

基本上我认为我的问题是为什么我不能从 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}])
  })
 },[])



Run Code Online (Sandbox Code Playgroud)

T.J*_*der 7

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

\n

要修复此问题,请使用回调版本setUserMessages:\xc2\xb9

\n
setUserMessages(allUserMessages => [...allUserMessages, {first_name: data.first_name,\n// \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^^^^^^^^^^^^^^^^^^\n    last_name: data.last_name,\n    avatar: data.avatar,\n    message: data.message,\n    account_type:data.account_type,\n    isMentioned: isUserMentioned\n}]);\n
Run Code Online (Sandbox Code Playgroud)\n

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

\n

一般来说,在 React 中,如果您要根据现有状态项更新状态项,99% 的情况下您希望使用状态设置器的回调版本,以便始终拥有最新状态。

\n
\n

\xc2\xb9 它确实应该被调用setAllUserMessages(或者状态项应该是userMessages而不是allUserMessages),因为状态项是allUserMessages。这只是惯例,但这是绝大多数常见的惯例。

\n

  • 谢谢你!我为此烦恼了很长时间,你明白了。我很感激,我只需这样做并将 setAllUserMessages 放入依赖项数组中即可。谢谢你,TJ (2认同)
  • @CharlesPettis - 很乐意提供帮助!您永远不需要将状态设置器放入依赖项数组中。React 保证它们永远不会改变。最好将其省略,这样很明显这是一种一次性效果。 (2认同)