React Hooks 首先在 Websockets 中发送消息

时间:2021-08-01 13:22:48

标签: reactjs websocket react-functional-component

我无法在后续点击后发送消息,如果我第一次点击按钮是向服务器发送消息,之后就不向服务器发送消息。

import { useEffect, useState, useRef } from "react";

import Header from "../src/Components/Header";
import ChatHistory from "../src/Components/ChatHistory";
import ChatArea from "../src/Components/ChatArea";

function App() {
  const [messages, setMessages] = useState([]);

  const testValue = { messages, setMessages };

  const socket = useRef(null);

  const renderCount = useRef(0);

  const sendMessage = (msg = "test") => {
    if (socket.current) {
      socket.current.send(msg);
    }
    addMessages(msg);
  };

  const addMessages = (msg) => {
    setMessages((prev) => [...prev, msg]);
  };

  useEffect(() => {
    socket.current = new WebSocket("ws://localhost:8001/ws");
    socket.current.onmessage = (msg) => {
      addMessages(msg);
    };
  }, []);

  useEffect(() => {
    return () => {
      if (socket.current) {
        socket.current.close();
      }
    };
  }, [socket]);

  console.log("i am rendering");

  return (
    <>
      <Header />
      <ChatHistory chatHistory={messages.current} />
      <div>
        <button onClick={sendMessage}>Send</button>
      </div>
    </>
  );
}

export default App;

上面提到的一个是我的代码,当第一次点击发送按钮时,它会触发向服务器发送消息,随后再次点击它不会向服务器发送消息。需要帮助。

2 个答案:

答案 0 :(得分:0)

您的第二个 useEffect 实际上在第一次渲染后关闭了连接,这是不必要的。

此外,您实际上并不需要将套接字实例保存在 ref 中,通常您只需要一个实例:

const socket = new WebSocket("ws://localhost:8001/ws");

function App() {
  const [messages, setMessages] = useState([]);

  const addMessages = (msg) => {
    setMessages((prev) => [...prev, msg]);
  };

  const sendMessage = (msg = "test") => {
    socket.send(msg);
    addMessages(msg);
  };

  // Setup
  useEffect(() => {
    socket.current.onmessage = addMessages;
  }, []);

  // Runs on App unmount, means on closing the application
  useEffect(() => {
    return () => {
      socket.close();
    };
  }, []);

  return (
    <>
      <Header />
      <ChatHistory chatHistory={messages.current} />
      <div>
        <button onClick={sendMessage}>Send</button>
      </div>
    </>
  );
}

答案 1 :(得分:0)

useEffect(() => {
    return () => {
      if (socket.current) {
        socket.current.close();
      }
    };
}, [socket]);

每当套接字发生变化时,你就关闭它
尝试在定义套接字的同一个 useEffect 中卸载

 useEffect(() => {
    if (!socket.current) {
        socket.current = new WebSocket("ws://localhost:8001/ws");
        socket.current.onmessage = (msg) => {
          addMessages(msg);
        };
    }
    return () => {
      if (socket.current) {
        socket.current.close();
      }
    };
  }, [socket]);

注意 useRef 不是这种情况的最佳选择,请改用 useState