I have created a web chat client using websocket, react hook, react functional components and typescript.
My questions is that it generates new one request of websocket after a client, which is built by react functional component with hook, sending or receiving a message to the other client, which is same built by react hook with functional component. I observe this situation from network tab with filtering websocket at browser dev tools. What I wish is there is only one websocket connection during chat.
But when I implement another client version using react class component type, this kind version only show one websocket during whole sending and receiving messages.
You can read the App.tsx
code frommy github repository . Below are exerpt of App.tsx
for react-hook type's client:
export const App: React.FC<{}> = ({}) => {
const [messages, setMessages] = useState<MessageType[]>([]);
const testValue = { messages, setMessages };
const ws = useRef(new WebSocket(URL));
const renderCount = useRef(0);
const submitMessage = (msg: MessageType) => {
ws.current.send(JSON.stringify(msg));
addMessage(msg);
};
const addMessage = (msg: MessageType) => {
setMessages([...messages, msg]);
};
// websocket onmessage
useEffect(() => {
ws.current.onmessage = (msg) => {
const message = JSON.parse(msg.data);
message.isMe = false;
addMessage(message);
};
console.log(`hello`);
});
// close websocket
useEffect(() => {
return () => {
ws.current.close();
};
}, [ws]);
return (
<StylesProvider injectFirst>
<div className="App" css={appStyle}>
<AppBar position="sticky">
{console.log(`renderCount: ${(renderCount.current += 1)}`)}
{/* debug */}
<Toolbar>
<IconButton edge="start" color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6">聊天室</Typography>
</Toolbar>
</AppBar>
<MessageHistory messages={messages} />
<ChatInput submitFC={submitMessage} />
</div>
</StylesProvider>
);
};
Below are screenshots of two local clients:
Receiver:
The repository of other client version built by react class component is at my github repository .
Chat server's repository is at my github another repository
I solve this problem based on this solution from other question at stackoverflow, but I don't know why. Version of react functional component with hook now can use only one websocket during a whole chat.
Below marked "// changed here" code are solution for App.tsx
:
export const App: React.FC<{}> = ({}) => {
const [messages, setMessages] = useState<MessageType[]>([]);
const testValue = { messages, setMessages };
// const ws = useRef(new WebSocket(URL));
const ws = useRef<WebSocket | null>(null); // changed here
const renderCount = useRef(0);
const submitMessage = (msg: MessageType) => {
if (ws.current) { // changed here
ws.current.send(JSON.stringify(msg));
} // changed here
addMessage(msg);
};
const addMessage = (msg: MessageType) => {
setMessages((prev) => { // changed here
return [...prev, msg]; // changed here
}); // changed here
};
// websocket onmessage
useEffect(() => {
ws.current = new WebSocket(URL); // changed here
ws.current.onmessage = (msg: MessageEvent) => { // changed here
const message = JSON.parse(msg.data);
message.isMe = false;
addMessage(message);
};
}, []); // changed here
// close websocket
useEffect(() => {
return () => {
if (ws.current) { // changed here
ws.current.close();
} // changed here
};
}, [ws]);
return (
<StylesProvider injectFirst>
<div className="App" css={appStyle}>
<AppBar position="sticky">
{console.log(`renderCount: ${(renderCount.current += 1)}`)}
{/* debug */}
<Toolbar>
<IconButton edge="start" color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6">聊天室</Typography>
</Toolbar>
</AppBar>
<MessageHistory messages={messages} />
<ChatInput submitFC={submitMessage} />
</div>
</StylesProvider>
);
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.