我正在使用Reaction和Socket构建一个实时聊天应用程序,以掌握基本知识.每当用户发送消息时,所有其他用户都会收到两次相同的消息.

我正在使用Reaction路由来提供一个加入‘页面’和一个聊天‘页面’.

function App() {
  return (
    <div className="App">

      <Router>
        <Routes>
          <Route path="/" element={<Join />} />
          <Route path="/chat/:name" element={<Chat />} />
        </Routes>
      </Router>

    </div>
  );
}

在聊天页面,也就是用户之间呈现消息的地方,我使用的是useEffect钩子,但我正在努力完全理解它.

function Chat () {
  const [messages, addMessage] = useState([{
    username: "chatbot",
    time: new Date(),
    message: "Welcome to the chatroom ????"
  }]);

  const location = useLocation();
  const [currentUser, updateUser] = useState(() => {
    const user = location.pathname.split('/chat/')[1];
    socket.emit("join_chat", {
      username: user
    })
    return user;
  });

  useEffect(() => {
    socket.on("receive_message", (data) => {
      console.log('received message');
      addMessage(prevMessages => {
        return [...prevMessages, {
          username: data.username,
          time: new Date(),
          message: data.message
        }]
      })
    })
  }, [socket])

  const sendMessage = (e) => {
    e.preventDefault();
    socket.emit("send_message", {
      message: currentMessage,
      username: currentUser,
    });

每次发送消息时,控制台日志(log)都会在接收端运行两次.

据我所知,钩子允许我们定义一些代码,这些代码将在DOM发生更改时运行,所以我不确定这种更改在哪里发生了两次?

我也不确定为什么这socket.on人一开始就应该住在useEffect号楼里.如果useEffect只是在重新呈现后立即调用,它如何仍然通过套接字接收每一条消息?

推荐答案

从你的描述来看,这听起来像是在将这款应用程序呈现为一个React.StrictMode组件,该组件运行特定的生命周期方法和功能两次,以帮助检测无意/意外的副作用.

效果会运行两次,意外/意外的副作用是代码为"receive_message"个事件添加了101个事件处理程序.

当组件卸载或socket依赖项更改时,缺少useEffect挂钩返回清除函数以取消订阅套接字/消息事件.

useEffect(() => {
  const handleMessage = (data) => {
    console.log('received message');
    addMessage(prevMessages => {
      return [...prevMessages, {
        username: data.username,
        time: new Date(),
        message: data.message
      }]
    });
  };

  socket.on("receive_message", handleMessage);

  return () => {
    socket.off("receive_message", handleMessage);
  };
}, [socket]);

据我所知,钩子允许我们定义一些代码 只要DOM发生更改,就会运行

useEffect挂钩允许您定义一些代码,当组件出于任何原因呈现时,这些代码将作为副作用运行.Reaction组件重新呈现的原因是(1)本地状态已更新,(2)Reactionprops 已更新,(3)父组件已重新呈现(for any of the same reasons).

我也不确定为什么socket.on人应该住在useEffect号楼里 首先.

Reaction组件中的"Render"方法将被视为纯函数.Reaction函数组件101100函数体为"Render"方法.订阅外部资源被认为是一种"不纯"行为,即它是一种副作用,应该只作为常规Reaction组件生命周期的一部分进行订阅.

Node.js相关问答推荐

如何使用多个OR参数从多个集合聚合

仅在一次查询中 MongoDB 上最近的一对位置

我应该转译我的 TypeScript 应用程序吗?

TypeError:在使用 Jest、Supertest、Express、Typescript 进行测试时无法读取未定义的属性(读取listen)

React Native:执行 com.android.build.gradle.internal.tasks.Workers$ActionFacade 时发生故障

(Mongoose) 删除 TTL 字段失败

一个非常奇怪的JavaScript heap out of memory问题

简单的 Node js 程序但执行顺序似乎不同?

Mongodb聚合传递一个匹配的数组和一个不匹配的数组

是Electron 的密码和登录凭据的安全存储吗?

在 node:readline 中按 CTRL+D 时会发出什么信号?

在 gatsby 中安装软件包时不推荐使用的错误

Node.js 表达的 Error 对象expose 了哪些属性?

NodeJS为exec设置环境变量

Node.js 服务器中没有缓存

Node.js 应用程序有周期性的缓慢和/或超时(不接受传入的请求)

User.findOrCreate 函数是做什么的,什么时候在Passport 中调用它?

需要 node-gyp 的 npm install 在 Windows 上失败

大型项目的 NodeJS vs Play 框架

FireStore 如果不存在则创建一个文档