具有功能组件的WebSocket [英] WebSockets with functional components

查看:52
本文介绍了具有功能组件的WebSocket的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的React应用程序中使用websockets.该应用程序应该仅由功能组件组成.

想象一下,该应用程序由两个选项卡"组成:一个不相关,另一个则是使用websocket进行的聊天.鉴于此,一旦用户进入聊天标签,我们就希望建立一个websocket连接.

组件应如何处理websocket对象?由于一旦用户切换回另一个选项卡( WebSocket.close()),我们就希望清理,这听起来像我们应该在此处使用效果钩子.

  const Chat =()=>{const [messages,setMessages] = useState([]);useEffect(()=> {const webSocket = new WebSocket("ws://url");webSocket.onmessage =(消息)=>{setMessages(prev => [... prev,message.data]);};return()=>webSocket.close();},[]);返回< p> {messages.join(")}</p> ;;}; 

行!但是现在,假设我们要在 useEffect 范围之外的某个地方引用 webSocket 变量-例如,我们希望在用户单击按钮后向服务器发送内容.

现在,应如何实施?我目前的想法(尽管我认为这是一个有缺陷的想法)是:

  const Chat =()=>{const [messages,setMessages] = useState([]);const [webSocket] = useState(new WebSocket("ws://url"));useEffect(()=> {webSocket.onmessage =(message)=>{setMessages(prev => [... prev,message.data]);};return()=>webSocket.close();},[]);返回< p> {messages.join(")}</p> ;;}; 

Kinda仍然可以工作,但是我觉得有更好的解决方案.

解决方案

正如@skyboyer在您的问题下的评论中所写,您可以使用 useRef 钩子来保存 WebSocket ,它将更加正确,因为您将不会更改或重新创建WebSocket对象.因此,您不需要 useState 挂钩.

useRef()钩不仅用于DOM引用."ref"对象是一个通用容器,其当前属性是可变的,并且可以保存任何值,类似于类上的实例属性.更多

因此您可以将代码更改为:

  const Chat =()=>{const [messages,setMessages] = useState([]);const webSocket = useRef(null);useEffect(()=> {webSocket.current =新的WebSocket("ws://url");webSocket.current.onmessage =(消息)=>{setMessages(prev => [... prev,message.data]);};return()=>webSocket.current.close();},[]);返回< p> {messages.join(")}</p> ;;}; 

I'm using websockets in my React application. The application is supposed to consist of function components only.

Imagine the application consists of two "tabs": one irrelevant, and the other one, a chat using websockets. Given that, we want to whip up a websocket connection once the user enters the chat tab.

How should the component handle the websocket object? Since we want to clean up once the user switches back to the other tab (WebSocket.close()), it sounds like we should be using an effect hook here.

const Chat = () => {
    const [messages, setMessages] = useState([]);
    useEffect(() => {
        const webSocket = new WebSocket("ws://url");
        webSocket.onmessage = (message) => {
            setMessages(prev => [...prev, message.data]);
        };
        return () => webSocket.close();
    }, []);
    return <p>{messages.join(" ")}</p>;
};

Works! But now, imagine we want to reference the webSocket variable somewhere outside the useEffect scope - say, we want to send something to the server once the user clicks a button.

Now, how should it be implemented? My current idea (albeit a flawed one, I feel) is:

const Chat = () => {
    const [messages, setMessages] = useState([]);
    const [webSocket] = useState(new WebSocket("ws://url"));
    useEffect(() => {
        webSocket.onmessage = (message) => {
            setMessages(prev => [...prev, message.data]);
        };
        return () => webSocket.close();
    }, []);
    return <p>{messages.join(" ")}</p>;
};

Kinda works, nevertheless I feel like there's a better solution.

解决方案

As @skyboyer has written in a comment under your question, you could use useRef hook to hold WebSocket and it will be more correct since you are not going to change or recreate WebSocket object. So you don't need useState hook.

The useRef() Hook isn’t just for DOM refs. The "ref" object is a generic container whose current property is mutable and can hold any value, similar to an instance property on a class. more

So you could change your code to:

const Chat = () => {
    const [messages, setMessages] = useState([]);
    const webSocket = useRef(null);

    useEffect(() => {
        webSocket.current = new WebSocket("ws://url");
        webSocket.current.onmessage = (message) => {
            setMessages(prev => [...prev, message.data]);
        };
        return () => webSocket.current.close();
    }, []);
    return <p>{messages.join(" ")}</p>;
};

这篇关于具有功能组件的WebSocket的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆