Skip to content

Commit

Permalink
feat: redux toolkit setup with socket middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
shubhamkashyapdev committed Feb 18, 2023
1 parent efe901f commit 48517f3
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 435 deletions.
9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@
"@nivo/bar": "^0.80.0",
"@nivo/core": "^0.80.0",
"@nivo/line": "^0.80.0",
"@reduxjs/toolkit": "^1.9.2",
"@tabler/icons": "^1.119.0",
"axios": "^1.2.2",
"dayjs": "^1.11.7",
"flowbite": "^1.5.5",
"flowbite-react": "^0.3.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-query": "^3.39.2",
"react-router-dom": "^6.5.0"
"react-redux": "^8.0.5",
"react-router-dom": "^6.5.0",
"socket.io-client": "^4.6.0"
},
"devDependencies": {
"@commitlint/cli": "^17.3.0",
Expand Down Expand Up @@ -86,4 +87,4 @@
"npx eslint --fix"
]
}
}
}
9 changes: 9 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ColorScheme } from '@mantine/core'
import { ColorSchemeProvider, MantineProvider } from '@mantine/core'
import { useHotkeys, useLocalStorage } from '@mantine/hooks'
import { useEffect } from 'react'
import { useDispatch } from 'react-redux'
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom'

import Layout from '@/components/Layout/Layout'
Expand All @@ -14,9 +15,17 @@ import {
ProductAnalytics,
Users
} from '@/screens'
import { socketConnecting } from '@/store/slice/socketSlice'
import { server } from '@/utils/server'

function App() {
// const socket = useSelector<RootState>((state) => state.socket) as InitialState

const dispatch = useDispatch()

useEffect(() => {
dispatch(socketConnecting(''))
}, [])
const [colorScheme, setColorScheme] = useLocalStorage<ColorScheme>({
key: 'mantine-color-scheme',
defaultValue: 'light',
Expand Down
15 changes: 10 additions & 5 deletions src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ import { ThemeProvider } from '@material-tailwind/react'
import React from 'react'
import ReactDOM from 'react-dom/client'
import { QueryClient, QueryClientProvider } from 'react-query'
import { Provider } from 'react-redux'

import store from '@/store/store'

import App from './App'

const queryClient = new QueryClient()

ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<React.StrictMode>
<ThemeProvider>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</ThemeProvider>
<Provider store={store}>
<ThemeProvider>
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
</ThemeProvider>
</Provider>
</React.StrictMode>
)
49 changes: 49 additions & 0 deletions src/store/middlewares/socketMiddleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/* eslint-disable no-console */
/* eslint-disable no-restricted-syntax */
import type { Middleware } from 'redux'
import type { Socket } from 'socket.io-client'
import { io } from 'socket.io-client'

import { socketActions, socketConnected } from '@/store/slice/socketSlice'

import { socketListeners } from './util'

export const socketMiddleware: Middleware = ({ dispatch, getState }) => {
let socket: Socket
return (next) => {
socket = io('http://localhost:8000', {})
socket.on('connect', () => {
dispatch(socketConnected(''))
console.log('socket connected!!')
})

// Register All Listeners Here
if (socket) {
for (const listner of socketListeners) {
if (!socket.hasListeners(listner)) {
socket.on(listner, (data: string) => console.log(data))
}
}
}
return (action) => {
// Socket
const isConnected = getState().socket.isConnected && socket

if (socketActions.socketDisconnected.match(action)) {
socket.on('disconnect', () => {
socket.close()
// @ts-ignore
socket = null
console.log('socket disconnected!!')
})
}

if (socketActions.socketGreet.match(action) && isConnected) {
socket.emit('greet', action.payload)
}

// Socket Ends
next(action)
}
}
}
1 change: 1 addition & 0 deletions src/store/middlewares/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const socketListeners = ['greet', 'ping']
9 changes: 9 additions & 0 deletions src/store/rootReducer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { combineReducers } from '@reduxjs/toolkit'

import { socketSliceReducer } from '@/store/slice/socketSlice'

const rootReducer = combineReducers({
socket: socketSliceReducer
})

export default rootReducer
46 changes: 46 additions & 0 deletions src/store/slice/socketSlice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { Slice } from '@reduxjs/toolkit'
import { createSlice } from '@reduxjs/toolkit'

import type { InitialState } from '@/store/types'

const initialState: InitialState = {
isConnecting: false,
isConnected: false,
socket: null
}

export const socketSlice: Slice<InitialState> = createSlice({
name: 'socketSlice',
initialState,
reducers: {
socketConnected: (state, action) => {
const { payload } = action
return {
...state,
isConnected: true,
isConnecting: false,
socket: payload
}
},
socketDisconnected: (state) => {
return {
...state,
isConnected: false,
isConnecting: false,
socket: null
}
},
socketConnecting: (state) => {
return state
},
socketGreet: (state) => {
return state
}
}
})

export const { socketConnected, socketConnecting, socketGreet } =
socketSlice.actions
export const socketActions = socketSlice.actions

export const socketSliceReducer = socketSlice.reducer
16 changes: 16 additions & 0 deletions src/store/store.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { configureStore } from '@reduxjs/toolkit'

import { socketMiddleware } from '@/store/middlewares/socketMiddleware'
import rootReducer from '@/store/rootReducer'

const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) => {
return getDefaultMiddleware().concat([socketMiddleware])
}
})

export default store

export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch
5 changes: 5 additions & 0 deletions src/store/types/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export type InitialState = {
isConnecting: boolean
isConnected: boolean
socket: null
}
7 changes: 2 additions & 5 deletions tailwind.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@
const withMT = require('@material-tailwind/react/utils/withMT')
/** @type {import('tailwindcss').Config} */
module.exports = withMT({
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'node_modules/flowbite-react/**/*.{js,jsx,ts,tsx}'
],
content: ['./src/**/*.{js,jsx,ts,tsx}'],
theme: {
extend: {}
},
plugins: [require('flowbite/plugin')]
plugins: []
})
Loading

0 comments on commit 48517f3

Please sign in to comment.