钩子回调时状态不正确 [英] Incorrect state upon hook callback

查看:24
本文介绍了钩子回调时状态不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 socket.io 和 react hooks 编写一个聊天客户端.调用 addMessage(收到消息事件后)时的消息历史记录 (chatMessages) 不正确(始终为空数组).chatMessages 确实更新(正确),但在下一次调用时它是空的.不应该有任何其他名为 chatMessages 的变量,并且消息在父类中(set 钩子起作用,所以我不明白为什么状态应该是无效的).状态似乎也不会再次更新,因此它似乎是添加消息中的某些内容.

import React, { useState, useCallback, useEffect } from "react";导入./styles/chat.css";从./utils/utils"导入{uuidv4};const SERVER_URL = "http://localhost:3337";const io = require("socket.io-client");功能聊天管理器(道具){//如何处理套接字(我们将它们存储在哪里)const [UId, setUId] = useState("");const [socket, setSocket] = useState(null);const [chatMessages, setChatMessages] = useState([]);const [role, setRole] = useState("Role");const useForceUpdate = () =>useState()[1];功能显示消息(味精){如果(UId){if (msg.user === UId) {返回 (<article class="msg-container msg-self" id="msg-0"><div class="msg-box"><div class="flr"><div class="messages"><p class="msg" id="msg-0">{msg.message}</p>

</文章>);} 别的 {返回 (<article class="msg-container msg-remote" id="msg-0"><div class="msg-box"><div class="flr"><div class="messages"><p class="msg" id="msg-0">{msg.message}</p>

</文章>);}}}函数添加消息(味精){console.log("消息:");控制台日志(味精);const newMessages = [...chatMessages];控制台日志(聊天消息);newMessages.push(msg);控制台日志(新消息);setChatMessages(newMessages);console.log("消息添加");}useEffect(() => {console.log("确实挂载了");如果(!套接字){setUId(uuidv4());console.log("设置UId");setSocket(io.connect(SERVER_URL));console.log("套接字安装");} 别的 {console.log("套接字发射");socket.emit("加入", {uid:UId,tid: "任务ID,稍后添加",角色:角色});socket.on(错误",函数(错误){console.log("收到套接字错误:");控制台日志(错误);});socket.on("message", function(msg) {添加消息(味精);});}返回 () =>{console.log("卸载");如果(套接字){socket.emit("离开", {uid:UId,tid: "任务ID,稍后添加",角色:角色});console.log("留言已发送");}};}, [插座]);函数发送消息(){const msg = "测试消息";socket.emit("usr_input", {uid:UId,tid: "任务ID,稍后添加",消息:消息,角色:角色});console.log("消息已发送");}返回 (<div><h1>这是聊天框</h1><聊天框sendMessage={sendMessage}chatMessages={chatMessages}displayMessage={displayMessage}/><h1>EOF</h1>

);}功能聊天框(道具){返回 (<section class="chatbox"><section id="chat-messages" class="chat-window">{props.chatMessages.map( (msg) => {props.displayMessage(msg)})}</节><form class="chat-input" onsubmit="return false;"><输入类型=文本"id="消息"自动完成=开"占位符="键入消息"/><button type="button" onClick={props.sendMessage}><svg风格={{宽度:24px",高度:24px"}}viewBox="0 0 24 24">{" "}<路径填充="rgba(0,0,0,.38)"d =M17,12L12,17V14H8V10H12V7L17,12M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2,12.12.2,12.5,2.2,128L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L5,8.09V15.91L12,19.85L19,15.91V8.09L12,4.15Z"/>{" "}</svg>{" "}</表单>

任何想法或解决方法将不胜感激!

解决方案

如果您改变了 chatMessages 的先前状态会怎样?

作为 useState 钩子 功能更新' 文档说明:

<块引用>

如果新状态是使用之前的状态计算出来的,你可以传递一个函数给 setState.该函数将接收先前的值,并返回更新的值.

也许你可以试试下面的代码片段:

function addMessage(msg) {setChatMessages(previousMessages => {返回 [...以前的消息,留言];});}

希望能帮到你!

I'm writing a chat client using socket.io and react hooks. The message history (chatMessages) when addMessage (upon receiving the message event) is called is incorrect (always an empty array). chatMessages does update (correctly), but on the next call it is empty. There shouldn't be any other variable named chatMessages and messages is in the parent class (the set hook works so I don’t see why the state should be invalid). The state doesn't appear to update again either, so it appears to something in add messages.

import React, { useState, useCallback, useEffect } from "react";
import "./styles/chat.css";
import { uuidv4 } from "./utils/utils";
const SERVER_URL = "http://localhost:3337";
const io = require("socket.io-client");


function ChatManager(props) {
  // How to handle sockets (where do we store them)
  const [UId, setUId] = useState("");
  const [socket, setSocket] = useState(null);
  const [chatMessages, setChatMessages] = useState([]);
  const [role, setRole] = useState("Role");
  const useForceUpdate = () => useState()[1];
  function displayMessage(msg) {
    if (UId) {
      if (msg.user === UId) {
        return (
          <article class="msg-container msg-self" id="msg-0">
            <div class="msg-box">
              <div class="flr">
                <div class="messages">
                  <p class="msg" id="msg-0">
                    {msg.message}
                  </p>
                </div>
              </div>
            </div>
          </article>
        );
      } else {
        return (
          <article class="msg-container msg-remote" id="msg-0">
            <div class="msg-box">
              <div class="flr">
                <div class="messages">
                  <p class="msg" id="msg-0">
                    {msg.message}
                  </p>
                </div>
              </div>
            </div>
          </article>
        );
      }
    }
  }

  function addMessage(msg) {
    console.log("message: ");
    console.log(msg);
    const newMessages = [...chatMessages];
    console.log(chatMessages);
    newMessages.push(msg);
    console.log(newMessages);
    setChatMessages(newMessages);
    console.log("Message added");

  }

  useEffect(() => {
    console.log("did mount");
    if (!socket) {
      setUId(uuidv4());
      console.log("Set UId");
      setSocket(io.connect(SERVER_URL));
      console.log("Socket mounted");
    } else {
      console.log("Socket emit");

      socket.emit("join", {
        uid: UId,
        tid: "Task ID, add later",
        role: role
      });

      socket.on("error", function(err) {
        console.log("received socket error:");
        console.log(err);
      });

      socket.on("message", function(msg) {
     addMessage(msg);
      });
    }
    return () => {
      console.log("Unmounting");
      if (socket) {
        socket.emit("leave", {
          uid: UId,
          tid: "Task ID, add later",
          role: role
        });
        console.log("Leaving message sent");
      }
    };
  }, [socket]);

  function sendMessage() {
    const msg = "Test message";
    socket.emit("usr_input", {
      uid: UId,
      tid: "Task ID, add later",
      message: msg,
      role: role
    });

    console.log("Message sent");
  }

return (
    <div>
      <h1> Here is the chatbox </h1>
      <ChatBox 
      sendMessage={sendMessage} 
      chatMessages={chatMessages}
      displayMessage={displayMessage}/>
      <h1> EOF </h1>
    </div>
  );
}

function ChatBox(props) {
  return (
    <section class="chatbox">
      <section id="chat-messages" class="chat-window">
        {props.chatMessages.map( (msg) => {props.displayMessage(msg)})}
      </section>

    <form class="chat-input" onsubmit="return false;">
        <input
          type="text"
          id="message"
          autocomplete="on"
          placeholder="Type a message"
        />
        <button type="button" onClick={props.sendMessage}>
          <svg
            style={{
              width: "24px",
              height: "24px"
            }}
            viewBox="0 0 24 24"
          >
            {" "}
            <path
              fill="rgba(0,0,0,.38)"
              d="M17,12L12,17V14H8V10H12V7L17,12M21,16.5C21,16.88 20.79,17.21 20.47,17.38L12.57,21.82C12.41,21.94 12.21,22 12,22C11.79,22 11.59,21.94 11.43,21.82L3.53,17.38C3.21,17.21 3,16.88 3,16.5V7.5C3,7.12 3.21,6.79 3.53,6.62L11.43,2.18C11.59,2.06 11.79,2 12,2C12.21,2 12.41,2.06 12.57,2.18L20.47,6.62C20.79,6.79 21,7.12 21,7.5V16.5M12,4.15L5,8.09V15.91L12,19.85L19,15.91V8.09L12,4.15Z"
            />{" "}
          </svg>{" "}
        </button>
      </form>

Any ideas or workarounds would be greatly appreciated!

解决方案

What about if you mutate the previous state of your chatMessages?

As the useState hook functional updates' documentation states:

If the new state is computed using the previous state, you can pass a function to setState. The function will receive the previous value, and return an updated value.

Maybe you can try as the following code snippet:

function addMessage(msg) {
  setChatMessages(previousMessages => {
    return [
      ...previousMessages,
      msg
    ];
  });
}

I hope that helps!

这篇关于钩子回调时状态不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆