mirror of
https://github.com/sergeyyarkov/educt-client.git
synced 2026-10-11 18:29:15 +03:00
fix: socket connection
This commit is contained in:
parent
283fc683c8
commit
e049ce7f71
@ -12,12 +12,17 @@ import { useRootStore } from '@educt/hooks/useRootStore';
|
|||||||
*/
|
*/
|
||||||
import PrivateRoute from '@educt/components/PrivateRoute';
|
import PrivateRoute from '@educt/components/PrivateRoute';
|
||||||
import PublicRoute from '@educt/components/PublicRoute';
|
import PublicRoute from '@educt/components/PublicRoute';
|
||||||
|
import { useSocketEvent } from './hooks/useSocketEvent';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const {
|
const {
|
||||||
uiStore: { history },
|
uiStore: { history },
|
||||||
} = useRootStore();
|
} = useRootStore();
|
||||||
|
|
||||||
|
useSocketEvent('connect', () => console.info('[WebSocket]: Connected.'));
|
||||||
|
useSocketEvent('disconnect', () => console.info('[WebSocket]: Disconnected.'));
|
||||||
|
useSocketEvent('connect_error', err => console.error(err));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Router history={history}>
|
<Router history={history}>
|
||||||
<Switch>
|
<Switch>
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { Suspense } from 'react';
|
import React, { Suspense, useContext } from 'react';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import { Redirect } from 'react-router';
|
import { Redirect } from 'react-router';
|
||||||
import { useErrorHandler } from 'react-error-boundary';
|
import { useErrorHandler } from 'react-error-boundary';
|
||||||
@ -23,6 +23,11 @@ import NavDesktop from '@educt/components/Nav/Desktop';
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useRootStore } from '@educt/hooks/useRootStore';
|
import { useRootStore } from '@educt/hooks/useRootStore';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contexts
|
||||||
|
*/
|
||||||
|
import { SocketContext } from '@educt/contexts';
|
||||||
|
|
||||||
type LayoutPropsType = { roles: UserRoleEnum[] | undefined };
|
type LayoutPropsType = { roles: UserRoleEnum[] | undefined };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,6 +35,7 @@ type LayoutPropsType = { roles: UserRoleEnum[] | undefined };
|
|||||||
*/
|
*/
|
||||||
const Layout: React.FC<LayoutPropsType> = ({ children, roles }) => {
|
const Layout: React.FC<LayoutPropsType> = ({ children, roles }) => {
|
||||||
const { userStore } = useRootStore();
|
const { userStore } = useRootStore();
|
||||||
|
const { socket } = useContext(SocketContext);
|
||||||
const handleError = useErrorHandler();
|
const handleError = useErrorHandler();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,6 +45,15 @@ const Layout: React.FC<LayoutPropsType> = ({ children, roles }) => {
|
|||||||
userStore.loadCurrentUserData().catch(error => handleError(error));
|
userStore.loadCurrentUserData().catch(error => handleError(error));
|
||||||
}, [handleError, userStore]);
|
}, [handleError, userStore]);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to websocket server
|
||||||
|
*/
|
||||||
|
useEffect(() => {
|
||||||
|
if (!socket?.connected) {
|
||||||
|
socket?.connect();
|
||||||
|
}
|
||||||
|
}, [socket]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header />
|
<Header />
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
import { useToast } from '@chakra-ui/react';
|
import { useToast } from '@chakra-ui/react';
|
||||||
|
import { SocketContext } from '@educt/contexts';
|
||||||
import { IToken } from '@educt/interfaces';
|
import { IToken } from '@educt/interfaces';
|
||||||
|
import { useContext } from 'react';
|
||||||
import { useErrorHandler } from 'react-error-boundary';
|
import { useErrorHandler } from 'react-error-boundary';
|
||||||
import useAsync from '../../useAsync';
|
import useAsync from '../../useAsync';
|
||||||
import { useRootStore } from '../../useRootStore';
|
import { useRootStore } from '../../useRootStore';
|
||||||
@ -8,6 +10,7 @@ type LoginResultDataType = IToken;
|
|||||||
|
|
||||||
const useLogin = () => {
|
const useLogin = () => {
|
||||||
const { authStore } = useRootStore();
|
const { authStore } = useRootStore();
|
||||||
|
const { socket } = useContext(SocketContext);
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const handleError = useErrorHandler();
|
const handleError = useErrorHandler();
|
||||||
|
|
||||||
@ -20,6 +23,7 @@ const useLogin = () => {
|
|||||||
isClosable: true,
|
isClosable: true,
|
||||||
status: 'success',
|
status: 'success',
|
||||||
});
|
});
|
||||||
|
socket?.connect();
|
||||||
return result.data;
|
return result.data;
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
if (error.response) {
|
if (error.response) {
|
||||||
|
|||||||
@ -3,11 +3,18 @@ import { useHistory } from 'react-router-dom';
|
|||||||
import { useRootStore } from '../../useRootStore';
|
import { useRootStore } from '../../useRootStore';
|
||||||
import { useErrorHandler } from 'react-error-boundary';
|
import { useErrorHandler } from 'react-error-boundary';
|
||||||
import useAsync from '../../useAsync';
|
import useAsync from '../../useAsync';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contexts
|
||||||
|
*/
|
||||||
|
import { SocketContext } from '@educt/contexts';
|
||||||
|
|
||||||
type LogoutResultDataType = Record<string, never>;
|
type LogoutResultDataType = Record<string, never>;
|
||||||
|
|
||||||
const useLogout = () => {
|
const useLogout = () => {
|
||||||
const { authStore } = useRootStore();
|
const { authStore } = useRootStore();
|
||||||
|
const { socket } = useContext(SocketContext);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const handleError = useErrorHandler();
|
const handleError = useErrorHandler();
|
||||||
@ -17,6 +24,7 @@ const useLogout = () => {
|
|||||||
const result = await authStore.logout();
|
const result = await authStore.logout();
|
||||||
history.push('/auth');
|
history.push('/auth');
|
||||||
toast({ title: 'You are logged out.', isClosable: true, status: 'info' });
|
toast({ title: 'You are logged out.', isClosable: true, status: 'info' });
|
||||||
|
socket?.disconnect();
|
||||||
return result.data;
|
return result.data;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
handleError(error);
|
handleError(error);
|
||||||
|
|||||||
@ -5,12 +5,12 @@ export const useSocket = (url: string) => {
|
|||||||
const [socket, setSocket] = useState<Socket | null>(null);
|
const [socket, setSocket] = useState<Socket | null>(null);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const socketClient = io(url, { autoConnect: true });
|
const socketClient = io(url, { autoConnect: false, withCredentials: true });
|
||||||
|
|
||||||
setSocket(socketClient);
|
setSocket(socketClient);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
socket?.disconnect();
|
socket?.close();
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useContext, useEffect } from 'react';
|
import { useContext, useEffect } from 'react';
|
||||||
import { SocketContext } from '@educt/contexts';
|
import { SocketContext } from '@educt/contexts';
|
||||||
|
|
||||||
export const useSocketEvent = (event: string, callback: () => void) => {
|
export const useSocketEvent = (event: string, callback: (...args: any) => void) => {
|
||||||
const { socket } = useContext(SocketContext);
|
const { socket } = useContext(SocketContext);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { useEffect, useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { Flex, Box, Text, Link, SimpleGrid, Divider } from '@chakra-ui/react';
|
import { Flex, Box, Text, Link, SimpleGrid, Divider } from '@chakra-ui/react';
|
||||||
import { Link as ReactRouterLink } from 'react-router-dom';
|
import { Link as ReactRouterLink } from 'react-router-dom';
|
||||||
import { IPageProps } from '@educt/interfaces';
|
import { IPageProps } from '@educt/interfaces';
|
||||||
@ -22,6 +22,8 @@ import {
|
|||||||
} from './components';
|
} from './components';
|
||||||
import { observer } from 'mobx-react';
|
import { observer } from 'mobx-react';
|
||||||
import { useFetchCourses, useFetchStat } from '@educt/hooks/queries';
|
import { useFetchCourses, useFetchStat } from '@educt/hooks/queries';
|
||||||
|
import { useSocketEvent } from '@educt/hooks/useSocketEvent';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main page
|
* Main page
|
||||||
@ -34,18 +36,20 @@ const MainPage: React.FC<IPageProps> = () => {
|
|||||||
const { data: stat } = useFetchStat();
|
const { data: stat } = useFetchStat();
|
||||||
const [online, setOnline] = useState<number>(0);
|
const [online, setOnline] = useState<number>(0);
|
||||||
|
|
||||||
// useEffect(() => {
|
/**
|
||||||
// const onUpdateOnline = users => {
|
* Update online state on socket event
|
||||||
// console.log(users);
|
*/
|
||||||
// setOnline(users.length);
|
useSocketEvent('user:online', online => setOnline(online));
|
||||||
// };
|
|
||||||
|
|
||||||
// socket.on('user:online', onUpdateOnline);
|
useSocketEvent('user:connected', user => {
|
||||||
|
console.table(user);
|
||||||
|
});
|
||||||
|
|
||||||
// return () => {
|
useEffect(() => {
|
||||||
// socket.off('user:online', onUpdateOnline);
|
if (stat) {
|
||||||
// };
|
setOnline(stat.online);
|
||||||
// }, [setOnline, socket]);
|
}
|
||||||
|
}, [stat?.online]);
|
||||||
|
|
||||||
if (me === null || courses === null || stat === null) return <LoadingPage />;
|
if (me === null || courses === null || stat === null) return <LoadingPage />;
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,7 @@ export const RootStoreProvider = ({ children }: { children: ReactNode }) => {
|
|||||||
* Socket context provider
|
* Socket context provider
|
||||||
*/
|
*/
|
||||||
export const SocketContextProvider: React.FC = ({ children }) => {
|
export const SocketContextProvider: React.FC = ({ children }) => {
|
||||||
const socket = useSocket('');
|
const socket = useSocket('ws://localhost:3333');
|
||||||
|
|
||||||
return <SocketContext.Provider value={{ socket }}>{children}</SocketContext.Provider>;
|
return <SocketContext.Provider value={{ socket }}>{children}</SocketContext.Provider>;
|
||||||
};
|
};
|
||||||
|
|||||||
1
src/types/index.d.ts
vendored
1
src/types/index.d.ts
vendored
@ -43,6 +43,7 @@ export type LessonProgress = {
|
|||||||
export type StatInfoType = {
|
export type StatInfoType = {
|
||||||
courses_count: string;
|
courses_count: string;
|
||||||
lessons_count: string;
|
lessons_count: string;
|
||||||
|
online: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type LessonVideoType = {
|
export type LessonVideoType = {
|
||||||
|
|||||||
@ -33,10 +33,6 @@ export default defineConfig({
|
|||||||
target: constants.BACKEND_URL,
|
target: constants.BACKEND_URL,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
'/socket.io': {
|
|
||||||
target: constants.BACKEND_URL,
|
|
||||||
changeOrigin: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
resolve: {
|
resolve: {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user