Simple demo of websocket + react

Time:2021-7-28

Simple demo of websocket + react

About demand

Function of simply receiving server information

Front end demand analysis

  • Acceptable server information
  • You can close the session
  • Restartable session

Knowledge demand

  • A little TS + react
  • A little node + Express
  • A little websocket

About the simplest demo

  • Front end implementation onlyStart websocketAndAccept sessionAs the key
  • The server node will realize the task of continuously sending information in the timer
import React, { useState, useRef, useLayoutEffect, useEffect } from 'react';

const App = () => {
  const ws = useRef<WebSocket | null>(null);
  const [message, setMessage] = useState('');
  //Start
  useLayoutEffect(() => {
    ws.current = new WebSocket('ws://localhost:7070');
    ws.current.onmessage = e => {
      setMessage(e.data);
    };
    return () => {
      ws.current?.close();
    };
  }, [ws]);


  return (
    <div className='App'>
      <div className='container'>
          {message}
      </div>
    </div>
  );
};

On active session and active switching mechanism

Familiarize yourself with the relevant methods

  • Websocket. Send() send session
  • Websocket. Close() closes the session
  • Websocket. Onmessage() accepts the session

In the example, the websocket link has been started when the component is rendered. It is necessary to actively open the websocket link according to the demand. The key WebSockets of the example need to be extracted

const webSocketInit = useCallback(() => {
    if (!ws.current) {
      ws.current = new WebSocket('ws://localhost:7070');
    }
  }, [ws]);

React likes immutable data. Usecallback is used here to wrap the relevant methods, so as to achieve the purpose of active link without causing multiple rendering

Outside the component life cycle, you may need to close the session to free the browser resources

useLayoutEffect(()=>{
  // do somting
  return ()=>{
    ws.current?.close();
  }
},[ws])

In the react hooks API, it is recommended to release resources in this way. Similarly, XXX can be used in the comment API to release resources

Code for final presentation

Personally, I think it’s best to have log printing in the final code. Using hooks API to monitor the status of websocket to print logs will be very laborious and cumbersome. Thanks to websocket’s own API, we can achieve good log printing

import React, { useState, useRef, useLayoutEffect, useCallback } from 'react';
import Header from './components/header';
import './App.less';

const App = () => {
  const ws = useRef<WebSocket | null>(null);
  const [message, setMessage] = useState('');
  Const [readyState, setreadystate] = usestate ('linking ');
  const [rdNum, SetRdNum] = useState<number>(0);

  /**
   *Pseudo random function, for testing
   *  */
  const getRandomInt = useCallback(() => {
    SetRdNum(Math.floor(Math.random() * Math.floor(999)));
  }, []);

  const webSocketInit = useCallback(() => {
    const stateArr = [
      'linking',
      'has been linked and can communicate',
      'connection closing',
      'connection closed or no link succeeded',
    ];
    if (!ws.current || ws.current.readyState === 3) {
      ws.current = new WebSocket('ws://localhost:7070');
      ws.current.onopen = _e =>
        setReadyState(stateArr[ws.current?.readyState ?? 0]);
      ws.current.onclose = _e =>
        setReadyState(stateArr[ws.current?.readyState ?? 0]);
      ws.current.onerror = e =>
        setReadyState(stateArr[ws.current?.readyState ?? 0]);
      ws.current.onmessage = e => {
        setMessage(e.data);
      };
    }
  }, [ws]);

  /**
   *Initialize websocket
   *The websocket acoustic method is used to obtain information
   *  */
  useLayoutEffect(() => {
    getRandomInt();
    webSocketInit();
    return () => {
      ws.current?.close();
    };
  }, [ws, getRandomInt, webSocketInit]);

  console.log('ws.readyState', ws.current?.readyState);

  return (
    <div className='App'>
      <Header status={readyState} />
      <div className='container'>
        <div>{message}</div>
        {/* <div>{readyState}</div> */}
        <div
          onClick={() => {
            ws.current?.close();
          }}>
          Clone
        </div>
        <div
          onClick={() => {
            getRandomInt();
            webSocketInit();
          }}>
          start
        </div>
        <div
          onClick={() => {
            if (ws.current?.readyState !== 1) {
              Console.log ('not linked successfully ');
              SetMessage ('linking ');
              return;
            }
            ws.current?.send(rdNum.toString());
          }}>
          ID:{rdNum}
        </div>
      </div>
    </div>
  );
};

export default App;

About QA

Q: Why not use socket.io?

Under simple requirements, it is not necessary to download a library. Learning websocket is also conducive to understanding the socket source code. Perhaps socket.io will be used in the project later

Q: Why do I initialize websocket in function commopent?

It is certain that external initialization is better to read and understand, as shown in the following examples:

import React from 'react';

const ws = new WebSocket('ws://loaclhost:7070');

const App = () => {
  // do ing...
};

Considering that the subsequent websocket status needs to be displayed in function commopent, the option of internal initialization is finally selected. At present, there are no excellent examples of external and acceptable status

Q: Why can’t I use the state of websocket.readystate directly to print the state?

Websocket.readystate does not actually update the status with the return message or operation. It needs to be actively obtained to sense the status update

About summary

This article may not be as fresh as personal notes

Thank you for reading!


About reference

Recommended Today

VBS obtains the operating system and its version number

VBS obtains the operating system and its version number ? 1 2 3 4 5 6 7 8 9 10 11 12 ‘************************************** ‘*by r05e ‘* operating system and its version number ‘************************************** strComputer = “.” Set objWMIService = GetObject(“winmgmts:” _  & “{impersonationLevel=impersonate}!\\” & strComputer & “\root\cimv2”) Set colOperatingSystems = objWMIService.ExecQuery _  (“Select * from […]