socket.io 多人井字棋-react_websocket

服务端: node socket.io express
客户端: react styled-component socket.io-client
​​​仓库​​​ 体验地址 ​​https://hongbin.xyz:3000​

连接

import io from "socket.io-client";

export const createConnect = (): SOCKET => io("https://hongbin.xyz:3000")

监听

socket.on(EVENT.CONNECT, () => {
console.log("connect success👏");
//设置context
handleSetSocketState({ status: true, socket });
//告诉服务端爷来了
socket.emit(EMIT.ENTER, nickname);
//服务端回应当前在线的用户(不算自己)
socket.on(EVENT.WELCOME, (allGamers) => {
allGamers = JSON.parse(allGamers);
console.log("allGamers:", allGamers);
setAllGamers(allGamers);
});
//监听新玩家进入
listenNewGamer(socket);
//监听新玩家退出
listenLeaveGame(socket);
//接收 对战邀请
socket.on(EVENT.FIGHT, (payload) => {
const fight = JSON.parse(payload);
setFightData((prev) => {
const fightData = { ...prev };
fightData[fight.nickname] = fight;
return fightData;
});
});
socket.on(EVENT.ACCEPTED_FIGHT, (payload: any) => {
const opponent = JSON.parse(payload); // props: nickname socketId
console.log("opponent:", opponent);
setOpponent(() => opponent);
//将 等待 变回 对战
handleRemoveWaitFight(opponent.nickname);
});
//对战邀请被拒绝
socket.on(EVENT.REJECTED_FIGHT, (payload) => {
const { nickname } = JSON.parse(payload);
handleRemoveWaitFight(nickname);
console.log("对战被" + nickname + "拒绝");
});
});

断开连接

const handleDisConnect = useCallback(() => {
socket.disconnect();
handleSetSocketState({ status: false, socket: {} });
setAllGamers(() => ({}));
}, [socket, handleSetSocketState]);

创建 context 保存 socket 全局使用

import { useState, createContext, useContext } from "react";

const defaultValue: any | TSocketContext = {
status: false,
socket: {},
nickname: localStorage.getItem(NICKNAME),
};

const Context: any = createContext(defaultValue);

const SocketContext = ({ children }: any) => {
const socketState = useState(defaultValue);

return <Context.Provider value={socketState}>{children}</Context.Provider>;
};

export default SocketContext;
export const useSocketContext: any | TSocketContext = () => useContext(Context);

Context 全部包裹

import SocketContext from "./api/context/SocketContext";

ReactDOM.render(
<ThemeProvider theme={{}}>
<GlobalStyle />
<SocketContext>
<App />
</SocketContext>
</ThemeProvider>,
document.getElementById("root")
);