feat: added some socket hooks

This commit is contained in:
Sergey Yarkov 2022-01-25 23:10:28 +03:00
parent d07879a700
commit 283fc683c8
10 changed files with 177 additions and 9 deletions

95
package-lock.json generated
View File

@ -1164,6 +1164,16 @@
"picomatch": "^2.2.2"
}
},
"@socket.io/base64-arraybuffer": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
"integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ=="
},
"@socket.io/component-emitter": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.0.0.tgz",
"integrity": "sha512-2pTGuibAXJswAPJjaKisthqS/NOK5ypG4LYT6tEAV0S/mxW0zOIvYvGK0V8w8+SHxAm6vRMSjqSalFXeBAqs+Q=="
},
"@types/history": {
"version": "4.7.9",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.9.tgz",
@ -1582,6 +1592,11 @@
"resolve": "^1.12.0"
}
},
"backo2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc="
},
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@ -1730,7 +1745,6 @@
"version": "4.3.2",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz",
"integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==",
"dev": true,
"requires": {
"ms": "2.1.2"
}
@ -1790,6 +1804,30 @@
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true
},
"engine.io-client": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.1.1.tgz",
"integrity": "sha512-V05mmDo4gjimYW+FGujoGmmmxRaDsrVr7AXA3ZIfa04MWM1jOfZfUwou0oNqhNwy/votUDvGDt4JA4QF4e0b4g==",
"requires": {
"@socket.io/component-emitter": "~3.0.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.0.0",
"has-cors": "1.1.0",
"parseqs": "0.0.6",
"parseuri": "0.0.6",
"ws": "~8.2.3",
"xmlhttprequest-ssl": "~2.0.0",
"yeast": "0.1.2"
}
},
"engine.io-parser": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz",
"integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==",
"requires": {
"@socket.io/base64-arraybuffer": "~1.0.2"
}
},
"enquirer": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz",
@ -2519,6 +2557,11 @@
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
"dev": true
},
"has-cors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk="
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@ -2973,8 +3016,7 @@
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"nanoclone": {
"version": "0.2.1",
@ -3122,6 +3164,16 @@
"lines-and-columns": "^1.1.6"
}
},
"parseqs": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
"integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w=="
},
"parseuri": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
"integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow=="
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
@ -3713,6 +3765,28 @@
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true
},
"socket.io-client": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.4.1.tgz",
"integrity": "sha512-N5C/L5fLNha5Ojd7Yeb/puKcPWWcoB/A09fEjjNsg91EDVr5twk/OEyO6VT9dlLSUNY85NpW6KBhVMvaLKQ3vQ==",
"requires": {
"@socket.io/component-emitter": "~3.0.0",
"backo2": "~1.0.2",
"debug": "~4.3.2",
"engine.io-client": "~6.1.1",
"parseuri": "0.0.6",
"socket.io-parser": "~4.1.1"
}
},
"socket.io-parser": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.1.1.tgz",
"integrity": "sha512-USQVLSkDWE5nbcY760ExdKaJxCE65kcsG/8k5FDGZVVxpD1pA7hABYXYkCUvxUuYYh/+uQw0N/fvBzfT8o07KA==",
"requires": {
"@socket.io/component-emitter": "~3.0.0",
"debug": "~4.3.1"
}
},
"source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
@ -4009,6 +4083,16 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
},
"ws": {
"version": "8.2.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz",
"integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA=="
},
"xmlhttprequest-ssl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A=="
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
@ -4020,6 +4104,11 @@
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="
},
"yeast": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk="
},
"yup": {
"version": "0.32.11",
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",

View File

@ -33,6 +33,7 @@
"react-router-dom": "^5.2.0",
"react-spinners": "^0.11.0",
"react-virtuoso": "^2.2.8",
"socket.io-client": "^4.4.1",
"validator": "^13.6.0",
"yup": "^0.32.9"
},

View File

@ -1,9 +1,14 @@
import { createContext } from 'react';
import { ChangeEmailPageContextType, CoursesPageContextType, UsersPageContextType } from '@educt/types';
import RootStore from '../stores/RootStore';
import { Socket } from 'socket.io-client';
export const StoreContext = createContext<RootStore | undefined>(undefined);
export const SocketContext = createContext<{ socket: Socket | null }>({
socket: null,
});
export const ChangeEmailPageContext = createContext<ChangeEmailPageContextType>({
isCodeSent: false,
setIsCodeSent: () => null,

18
src/hooks/useSocket.ts Normal file
View File

@ -0,0 +1,18 @@
import { io, Socket } from 'socket.io-client';
import { useEffect, useState } from 'react';
export const useSocket = (url: string) => {
const [socket, setSocket] = useState<Socket | null>(null);
useEffect(() => {
const socketClient = io(url, { autoConnect: true });
setSocket(socketClient);
return () => {
socket?.disconnect();
};
}, []);
return socket;
};

View File

@ -0,0 +1,18 @@
import { useContext, useEffect } from 'react';
import { SocketContext } from '@educt/contexts';
export const useSocketEvent = (event: string, callback: () => void) => {
const { socket } = useContext(SocketContext);
useEffect(() => {
if (!socket) {
return;
}
socket.on(event, callback);
return () => {
socket.off(event, callback);
};
}, [callback, event, socket]);
};

View File

@ -3,14 +3,16 @@ import ReactDOM from 'react-dom';
import { ChakraProvider, ColorModeScript } from '@chakra-ui/react';
import App from './App';
import { theme } from './theme';
import { RootStoreProvider } from './providers';
import { RootStoreProvider, SocketContextProvider } from './providers';
ReactDOM.render(
<>
<ColorModeScript />
<RootStoreProvider>
<ChakraProvider theme={theme}>
<App />
<SocketContextProvider>
<App />
</SocketContextProvider>
</ChakraProvider>
</RootStoreProvider>
</>,

View File

@ -13,6 +13,7 @@ export interface IAppConfig {
}
export interface IToken {
userId: string;
token: string;
type: string;
expires_at: string;

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { Flex, Box, Text, Link, SimpleGrid, Divider } from '@chakra-ui/react';
import { Link as ReactRouterLink } from 'react-router-dom';
import { IPageProps } from '@educt/interfaces';
@ -32,6 +32,20 @@ const MainPage: React.FC<IPageProps> = () => {
} = useRootStore();
const { data: courses } = useFetchCourses({ limit: 3 });
const { data: stat } = useFetchStat();
const [online, setOnline] = useState<number>(0);
// useEffect(() => {
// const onUpdateOnline = users => {
// console.log(users);
// setOnline(users.length);
// };
// socket.on('user:online', onUpdateOnline);
// return () => {
// socket.off('user:online', onUpdateOnline);
// };
// }, [setOnline, socket]);
if (me === null || courses === null || stat === null) return <LoadingPage />;
@ -43,7 +57,7 @@ const MainPage: React.FC<IPageProps> = () => {
<Stat>
<StatLabel>Online</StatLabel>
<StatContent>
<StatNumber>24</StatNumber>
<StatNumber>{online}</StatNumber>
<StatIcon icon={MdOutlineGroup} />
</StatContent>
</Stat>

View File

@ -1,9 +1,16 @@
import React, { useState, ReactNode } from 'react';
import { ChangeEmailPageContext, CoursesPageContext, StoreContext, UsersPageContext } from '@educt/contexts';
import {
ChangeEmailPageContext,
CoursesPageContext,
SocketContext,
StoreContext,
UsersPageContext,
} from '@educt/contexts';
import { ConfirmEmailDataType, SearchingRoleStateType } from '@educt/types';
import RootStore from '@educt/stores/RootStore';
import { ICategory, ICourse, IUser } from '@educt/interfaces';
import { ICategory } from '@educt/interfaces';
import { CourseStatusEnum } from '@educt/enums';
import { useSocket } from '@educt/hooks/useSocket';
/**
* Root store context provider
@ -14,6 +21,15 @@ export const RootStoreProvider = ({ children }: { children: ReactNode }) => {
return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>;
};
/**
* Socket context provider
*/
export const SocketContextProvider: React.FC = ({ children }) => {
const socket = useSocket('');
return <SocketContext.Provider value={{ socket }}>{children}</SocketContext.Provider>;
};
/**
* Change email page context provider
*/

View File

@ -33,6 +33,10 @@ export default defineConfig({
target: constants.BACKEND_URL,
changeOrigin: true,
},
'/socket.io': {
target: constants.BACKEND_URL,
changeOrigin: true,
},
},
},
resolve: {