diff --git a/src/components/App/Helper/AskQuestion/index.tsx b/src/components/App/Helper/AskQuestion/index.tsx index ca1d223b3..f1b2d14c3 100644 --- a/src/components/App/Helper/AskQuestion/index.tsx +++ b/src/components/App/Helper/AskQuestion/index.tsx @@ -1,6 +1,6 @@ import { TextareaAutosize } from '@mui/base' import { FormControl, InputLabel, MenuItem, OutlinedInput, Select, SelectChangeEvent } from '@mui/material' -import { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import { MdSend } from 'react-icons/md' import { PropagateLoader } from 'react-spinners' import { toast } from 'react-toastify' @@ -10,7 +10,7 @@ import styled from 'styled-components' import { Flex } from '~/components/common/Flex' import { Text } from '~/components/common/Text' import { ToastMessage } from '~/components/common/Toast/toastMessage' -import useSocket from '~/hooks/useSockets' +import { useSocket } from '~/hooks/useSockets' import { postAskQuestion } from '~/network/fetchGraphData' import { useAppStore } from '~/stores/useAppStore' import { useDataStore } from '~/stores/useDataStore' @@ -42,8 +42,9 @@ export const AskQuestion = () => { const [question, setQuestion] = useState('') const [selectedValue, setSelectedValue] = useState('Beginner') const searchTerm = useAppStore((s) => s.currentSearch) - const isSocketSet: { current: boolean } = useRef(false) - const socket: Socket | null = useSocket() + + const socket: Socket | undefined = useSocket() + const [setBudget] = useUserStore((s) => [s.setBudget]) const [askedQuestions, askedQuestionsAnswers, setAskedQuestion, setAskedQuestionAnswer, hasQuestionInProgress] = @@ -68,16 +69,12 @@ export const AskQuestion = () => { ) useEffect(() => { - if (isSocketSet.current) { + if (!socket) { return } if (handleAskQuestion) { - if (socket) { - socket.on('askquestionhook', handleAskQuestion) - - isSocketSet.current = true - } + socket.on('askquestionhook', handleAskQuestion) } }, [handleAskQuestion, socket]) diff --git a/src/components/App/Helper/TeachMe/index.tsx b/src/components/App/Helper/TeachMe/index.tsx index 3753cecd5..73e0c0f42 100644 --- a/src/components/App/Helper/TeachMe/index.tsx +++ b/src/components/App/Helper/TeachMe/index.tsx @@ -9,7 +9,6 @@ import styled from 'styled-components' import { Flex } from '~/components/common/Flex' import { Text } from '~/components/common/Text' import { ToastMessage } from '~/components/common/Toast/toastMessage' -import useSocket from '~/hooks/useSockets' import { postInstagraph, postTeachMe } from '~/network/fetchGraphData' import { useAppStore } from '~/stores/useAppStore' import { useDataStore } from '~/stores/useDataStore' @@ -20,6 +19,7 @@ import { updateBudget } from '~/utils/setBudget' import { AskQuestion } from '../AskQuestion' import 'reactflow/dist/style.css' +import { useSocket } from '~/hooks/useSockets' type ResponseType = { tutorial: string @@ -31,7 +31,7 @@ export const TeachMe = () => { const [setBudget] = useUserStore((s) => [s.setBudget]) const isSocketSet: { current: boolean } = useRef(false) - const socket: Socket | null = useSocket() + const socket: Socket | undefined = useSocket() const [setTeachMeAnswer, setHasTeachingInProgress, setInstagraphAnswer, setHasInstagraphInProgress] = useTeachStore( (s) => [s.setTeachMeAnswer, s.setHasTeachingInProgress, s.setInstagraphAnswer, s.setHasInstagraphInProgress], @@ -62,24 +62,18 @@ export const TeachMe = () => { ) useEffect(() => { - if (isSocketSet.current) { + if (!socket) { return } if (handleTeachMe) { - if (socket) { - socket.on('teachmehook', handleTeachMe) - - isSocketSet.current = true - } + socket.on('teachmehook', handleTeachMe) } if (handleInstagraph) { - if (socket) { - socket.on('instagraphhook', handleInstagraph) + socket.on('instagraphhook', handleInstagraph) - isSocketSet.current = true - } + isSocketSet.current = true } }, [socket, handleTeachMe, handleInstagraph]) diff --git a/src/components/App/Providers/Socket/SocketContext.ts b/src/components/App/Providers/Socket/SocketContext.ts new file mode 100644 index 000000000..ee084240a --- /dev/null +++ b/src/components/App/Providers/Socket/SocketContext.ts @@ -0,0 +1,21 @@ +// SocketContext.ts +import { createContext, useContext } from 'react' +import { Socket } from 'socket.io-client' + +interface SocketContextType { + socket: Socket +} + +const SocketContext = createContext(undefined) + +export const useSocket = () => { + const context = useContext(SocketContext) + + if (!context) { + throw new Error('useSocket must be used within a SocketProvider') + } + + return context.socket +} + +export default SocketContext diff --git a/src/components/App/Providers/Socket/index.tsx b/src/components/App/Providers/Socket/index.tsx new file mode 100644 index 000000000..a20ef924e --- /dev/null +++ b/src/components/App/Providers/Socket/index.tsx @@ -0,0 +1,17 @@ +// SocketProvider.tsx +import { FC, ReactNode } from 'react' +import { io } from 'socket.io-client' +import { API_URL } from '~/constants' +import SocketContext from './SocketContext' + +interface SocketProviderProps { + children: ReactNode +} + +const contextValue = { + socket: io(API_URL), +} + +export const SocketProvider: FC = ({ children }) => ( + {children} +) diff --git a/src/components/App/Providers/index.tsx b/src/components/App/Providers/index.tsx index 0bbbbc035..ef2fd884a 100644 --- a/src/components/App/Providers/index.tsx +++ b/src/components/App/Providers/index.tsx @@ -9,6 +9,7 @@ import { ThemeProvider as StyleThemeProvider } from 'styled-components' import { colors } from '~/utils/colors' import { breakpoints } from '~/utils/media' import { MuiButton } from './MuiButton' +import { SocketProvider } from './Socket' const palette = createPalette({ mode: 'dark', @@ -50,7 +51,9 @@ export const AppProviders: FC = ({ children }) => ( - {children} + + {children} + ) diff --git a/src/components/App/index.tsx b/src/components/App/index.tsx index 328ab0cfc..28ba6b531 100644 --- a/src/components/App/index.tsx +++ b/src/components/App/index.tsx @@ -1,4 +1,4 @@ -import { Suspense, lazy, useCallback, useEffect, useRef } from 'react' +import { Suspense, lazy, useCallback, useEffect } from 'react' import { FormProvider, useForm } from 'react-hook-form' import 'react-toastify/dist/ReactToastify.css' import { Socket } from 'socket.io-client' @@ -6,7 +6,7 @@ import styled from 'styled-components' import { DataRetriever } from '~/components/DataRetriever' import { GlobalStyle } from '~/components/GlobalStyle' import { Flex } from '~/components/common/Flex' -import useSocket from '~/hooks/useSockets' +import { useSocket } from '~/hooks/useSockets' import { getGraphDataPositions } from '~/network/fetchGraphData/const' import { useAppStore } from '~/stores/useAppStore' import { useDataStore } from '~/stores/useDataStore' @@ -20,7 +20,6 @@ import { ActionsToolbar } from './ActionsToolbar' import { AppBar } from './AppBar' import { DeviceCompatibilityNotice } from './DeviceCompatibilityNotification' import { Helper } from './Helper' -import { AppProviders } from './Providers' import { SecondarySideBar } from './SecondarySidebar' import { Toasts } from './Toasts' @@ -77,9 +76,7 @@ export const App = () => { useDataStore((s) => s.setCategoryFilter), ] - const isSocketSet: { current: boolean } = useRef(false) - - const socket: Socket | null = useSocket() + const socket: Socket | undefined = useSocket() const form = useForm<{ search: string }>({ mode: 'onChange' }) @@ -126,19 +123,29 @@ export const App = () => { // setup socket useEffect(() => { - if (isSocketSet.current) { - return - } - if (socket) { - socket.on('newnode', handleNewNode) + socket.on('connect_error', (error: unknown) => { + console.error('Socket connection error:', error) + }) - isSocketSet.current = true + socket.on('connect', () => console.log('connected')) + socket.on('disconnect', () => console.log('disconnected')) + socket.on('newnode', handleNewNode) } }, [socket, handleNewNode]) + useEffect( + () => () => { + if (socket) { + console.log('disc') + socket.disconnect() + } + }, + [socket], + ) + return ( - + <> @@ -168,6 +175,6 @@ export const App = () => { - + ) } diff --git a/src/components/AppContainer/index.tsx b/src/components/AppContainer/index.tsx index 4a42ad5c0..62214db17 100644 --- a/src/components/AppContainer/index.tsx +++ b/src/components/AppContainer/index.tsx @@ -1,5 +1,6 @@ import { Suspense, lazy, useState } from 'react' import { E2ETests } from '~/utils' +import { AppProviders } from '../App/Providers' import { Auth } from '../Auth' const LazyApp = lazy(() => import('../App').then(({ App }) => ({ default: App }))) @@ -8,11 +9,11 @@ export const AppContainer = () => { const [authenticated, setAuthenticated] = useState(false) return ( - <> + Loading...}> {!authenticated ? : } - + ) } diff --git a/src/hooks/useSockets/index.ts b/src/hooks/useSockets/index.ts index ee0a37cee..227ecf077 100644 --- a/src/hooks/useSockets/index.ts +++ b/src/hooks/useSockets/index.ts @@ -1,23 +1,8 @@ -// useSocket.ts +import { useContext } from 'react' +import SocketContext from '~/components/App/Providers/Socket/SocketContext' -import { useEffect, useState } from 'react' -import { Socket, io } from 'socket.io-client' -import { API_URL } from '~/constants' +export const useSocket = () => { + const context = useContext(SocketContext) -const useSocket = (): Socket | null => { - const [socket, setSocket] = useState(null) - - useEffect(() => { - const socketInstance = io(API_URL) - - setSocket(socketInstance) - - return () => { - socketInstance.disconnect() - } - }, []) - - return socket + return context?.socket } - -export default useSocket