Migrating from Redux to RTK-query
This commit is contained in:
@@ -20,6 +20,7 @@
|
|||||||
"@dnd-kit/utilities": "^3.2.1",
|
"@dnd-kit/utilities": "^3.2.1",
|
||||||
"@fortawesome/fontawesome-free": "^6.3.0",
|
"@fortawesome/fontawesome-free": "^6.3.0",
|
||||||
"@redux-devtools/extension": "^3.2.5",
|
"@redux-devtools/extension": "^3.2.5",
|
||||||
|
"@reduxjs/toolkit": "^1.9.7",
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||||
"@tanstack/react-table": "^8.9.3",
|
"@tanstack/react-table": "^8.9.3",
|
||||||
"@types/mime-types": "^2.1.0",
|
"@types/mime-types": "^2.1.0",
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import {
|
|||||||
SETTINGS_CALL_IN_PROGRESS,
|
SETTINGS_CALL_IN_PROGRESS,
|
||||||
SETTINGS_DB_FLUSH_SUCCESS,
|
SETTINGS_DB_FLUSH_SUCCESS,
|
||||||
SETTINGS_QBITTORRENT_TORRENTS_LIST_FETCHED,
|
SETTINGS_QBITTORRENT_TORRENTS_LIST_FETCHED,
|
||||||
} from "../constants/action-types";
|
} from "../reducers/settings.reducer";
|
||||||
import {
|
import {
|
||||||
LIBRARY_SERVICE_BASE_URI,
|
LIBRARY_SERVICE_BASE_URI,
|
||||||
SETTINGS_SERVICE_BASE_URI,
|
SETTINGS_SERVICE_BASE_URI,
|
||||||
@@ -72,20 +72,19 @@ export const flushDb = () => async (dispatch) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getQBitTorrentClientInfo = (hostInfo) => async (dispatch) => {
|
export const getQBitTorrentClientInfo = (hostInfo) => async (dispatch) => {
|
||||||
const foo = await axios.request({
|
await axios.request({
|
||||||
url: `${QBITTORRENT_SERVICE_BASE_URI}/connect`,
|
url: `${QBITTORRENT_SERVICE_BASE_URI}/connect`,
|
||||||
method: "POST",
|
method: "POST",
|
||||||
data: hostInfo,
|
data: hostInfo,
|
||||||
});
|
});
|
||||||
const bar = await axios.request({
|
const qBittorrentClientInfo = await axios.request({
|
||||||
url: `${QBITTORRENT_SERVICE_BASE_URI}/getClientInfo`,
|
url: `${QBITTORRENT_SERVICE_BASE_URI}/getClientInfo`,
|
||||||
method: "GET",
|
method: "GET",
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(bar);
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: SETTINGS_QBITTORRENT_TORRENTS_LIST_FETCHED,
|
type: SETTINGS_QBITTORRENT_TORRENTS_LIST_FETCHED,
|
||||||
data: bar.data,
|
data: qBittorrentClientInfo.data,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,6 @@ export const App = (): ReactElement => {
|
|||||||
<AirDCPPSocketContextProvider>
|
<AirDCPPSocketContextProvider>
|
||||||
<div>
|
<div>
|
||||||
<AirDCPPSocketComponent />
|
<AirDCPPSocketComponent />
|
||||||
<Navbar />
|
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Dashboard />} />
|
<Route path="/" element={<Dashboard />} />
|
||||||
<Route path="/import" element={<Import path={"./comics"} />} />
|
<Route path="/import" element={<Import path={"./comics"} />} />
|
||||||
|
|||||||
@@ -16,110 +16,50 @@ import Header from "../shared/Header";
|
|||||||
|
|
||||||
export const Dashboard = (): ReactElement => {
|
export const Dashboard = (): ReactElement => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
dispatch(fetchVolumeGroups());
|
// dispatch(fetchVolumeGroups());
|
||||||
dispatch(
|
// dispatch(
|
||||||
getComicBooks({
|
// getComicBooks({
|
||||||
paginationOptions: {
|
// paginationOptions: {
|
||||||
page: 0,
|
// page: 0,
|
||||||
limit: 5,
|
// limit: 5,
|
||||||
sort: { updatedAt: "-1" },
|
// sort: { updatedAt: "-1" },
|
||||||
},
|
// },
|
||||||
predicate: { "acquisition.source.wanted": false },
|
// predicate: { "acquisition.source.wanted": false },
|
||||||
comicStatus: "recent",
|
// comicStatus: "recent",
|
||||||
}),
|
// }),
|
||||||
);
|
// );
|
||||||
dispatch(
|
// dispatch(
|
||||||
getComicBooks({
|
// getComicBooks({
|
||||||
paginationOptions: {
|
// paginationOptions: {
|
||||||
page: 0,
|
// page: 0,
|
||||||
limit: 5,
|
// limit: 5,
|
||||||
sort: { updatedAt: "-1" },
|
// sort: { updatedAt: "-1" },
|
||||||
},
|
// },
|
||||||
predicate: { "acquisition.source.wanted": true },
|
// predicate: { "acquisition.source.wanted": true },
|
||||||
comicStatus: "wanted",
|
// comicStatus: "wanted",
|
||||||
}),
|
// }),
|
||||||
);
|
// );
|
||||||
dispatch(getLibraryStatistics());
|
// dispatch(getLibraryStatistics());
|
||||||
}, []);
|
// }, []);
|
||||||
|
//
|
||||||
const recentComics = useSelector(
|
// const recentComics = useSelector(
|
||||||
(state: RootState) => state.fileOps.recentComics,
|
// (state: RootState) => state.fileOps.recentComics,
|
||||||
);
|
// );
|
||||||
const wantedComics = useSelector(
|
// const wantedComics = useSelector(
|
||||||
(state: RootState) => state.fileOps.wantedComics,
|
// (state: RootState) => state.fileOps.wantedComics,
|
||||||
);
|
// );
|
||||||
const volumeGroups = useSelector(
|
// const volumeGroups = useSelector(
|
||||||
(state: RootState) => state.fileOps.comicVolumeGroups,
|
// (state: RootState) => state.fileOps.comicVolumeGroups,
|
||||||
);
|
// );
|
||||||
|
//
|
||||||
const libraryStatistics = useSelector(
|
// const libraryStatistics = useSelector(
|
||||||
(state: RootState) => state.comicInfo.libraryStatistics,
|
// (state: RootState) => state.comicInfo.libraryStatistics,
|
||||||
);
|
// );
|
||||||
return (
|
return (
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<section className="section">
|
<section className="section">
|
||||||
<h1 className="title">Dashboard</h1>
|
<h1 className="title">Dashboard</h1>
|
||||||
|
|
||||||
{!isEmpty(recentComics) ? (
|
|
||||||
<>
|
|
||||||
{/* Pull List */}
|
|
||||||
<PullList issues={recentComics} />
|
|
||||||
<>
|
|
||||||
<div className="content mt-6">
|
|
||||||
<Header
|
|
||||||
headerContent="Import Activity"
|
|
||||||
subHeaderContent="Results aggregated from the last import"
|
|
||||||
iconClassNames="fa-solid fa-file-invoice mr-2"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table className="table">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>
|
|
||||||
<abbr title="Position">Pos</abbr>
|
|
||||||
</th>
|
|
||||||
<th>Team</th>
|
|
||||||
<th>
|
|
||||||
<abbr title="Played">Pld</abbr>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<th>1</th>
|
|
||||||
<td>38</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</>
|
|
||||||
|
|
||||||
{/* Stats */}
|
|
||||||
{!isEmpty(libraryStatistics) && (
|
|
||||||
<LibraryStatistics stats={libraryStatistics} />
|
|
||||||
)}
|
|
||||||
{/* Wanted comics */}
|
|
||||||
{!isEmpty(wantedComics) && (
|
|
||||||
<WantedComicsList comics={wantedComics} />
|
|
||||||
)}
|
|
||||||
{/* Recent imports */}
|
|
||||||
<RecentlyImported comicBookCovers={recentComics} />
|
|
||||||
|
|
||||||
{/* Volumes */}
|
|
||||||
{!isEmpty(volumeGroups) && (
|
|
||||||
<VolumeGroups volumeGroups={volumeGroups} />
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<ZeroState
|
|
||||||
header={"Set the source directory"}
|
|
||||||
message={
|
|
||||||
"No comics were found! Please point ThreeTwo! to a directory..."
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -34,7 +34,11 @@ export const AirDCPPSettingsForm = (): ReactElement => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ConnectionForm initialData={initFormData} submitHandler={onSubmit} />
|
<ConnectionForm
|
||||||
|
initialData={initFormData}
|
||||||
|
submitHandler={onSubmit}
|
||||||
|
formHeading={"Configure AirDC++"}
|
||||||
|
/>
|
||||||
|
|
||||||
{!isEmpty(airDCPPSettings.airDCPPState.socketConnectionInformation) ? (
|
{!isEmpty(airDCPPSettings.airDCPPState.socketConnectionInformation) ? (
|
||||||
<AirDCPPSettingsConfirmation
|
<AirDCPPSettingsConfirmation
|
||||||
|
|||||||
@@ -1,27 +1,14 @@
|
|||||||
import React, { ReactElement, useCallback, useEffect } from "react";
|
import React, { ReactElement, useCallback, useEffect } from "react";
|
||||||
import { useDispatch, useSelector } from "react-redux";
|
import { useAppDispatch, useAppSelector } from "../../../hooks/store";
|
||||||
import { getQBitTorrentClientInfo } from "../../../actions/settings.actions";
|
import { getQBitTorrentClientInfo } from "../../../actions/settings.actions";
|
||||||
import { saveSettings } from "../../../actions/settings.actions";
|
import { saveSettings } from "../../../actions/settings.actions";
|
||||||
import { ConnectionForm } from "../../shared/ConnectionForm/ConnectionForm";
|
import { ConnectionForm } from "../../shared/ConnectionForm/ConnectionForm";
|
||||||
|
import { useGetAllSettingsQuery } from "../../../services/settings.api";
|
||||||
import { isUndefined } from "lodash";
|
import { isUndefined } from "lodash";
|
||||||
|
import { useConnectToQBittorrentClientQuery } from "../../../services/torrents.api";
|
||||||
|
|
||||||
export const QbittorrentConnectionForm = (): ReactElement => {
|
export const QbittorrentConnectionForm = (): ReactElement => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const torrents = useSelector(
|
|
||||||
(state: RootState) => state.settings.torrentsList,
|
|
||||||
);
|
|
||||||
|
|
||||||
const qBittorrentSettings = useSelector((state: RootState) => {
|
|
||||||
if (!isUndefined(state.settings.data.bittorrent)) {
|
|
||||||
return state.settings.data.bittorrent.client.host;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isUndefined(qBittorrentSettings)) {
|
|
||||||
dispatch(getQBitTorrentClientInfo(qBittorrentSettings));
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onSubmit = useCallback(async (values) => {
|
const onSubmit = useCallback(async (values) => {
|
||||||
try {
|
try {
|
||||||
@@ -31,15 +18,7 @@ export const QbittorrentConnectionForm = (): ReactElement => {
|
|||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return <></>;
|
||||||
<>
|
|
||||||
<ConnectionForm
|
|
||||||
initialData={qBittorrentSettings}
|
|
||||||
submitHandler={onSubmit}
|
|
||||||
/>
|
|
||||||
<pre> {torrents && JSON.stringify(torrents, null, 4)} </pre>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default QbittorrentConnectionForm;
|
export default QbittorrentConnectionForm;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { isEmpty } from "lodash";
|
|||||||
export const ConnectionForm = ({
|
export const ConnectionForm = ({
|
||||||
initialData,
|
initialData,
|
||||||
submitHandler,
|
submitHandler,
|
||||||
|
formHeading,
|
||||||
}): ReactElement => {
|
}): ReactElement => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -14,8 +15,8 @@ export const ConnectionForm = ({
|
|||||||
initialValues={initialData}
|
initialValues={initialData}
|
||||||
render={({ handleSubmit }) => (
|
render={({ handleSubmit }) => (
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<h2>Configure AirDC++</h2>
|
<h2>{formHeading}</h2>
|
||||||
<label className="label">AirDC++ Hostname</label>
|
<label className="label">Hostname</label>
|
||||||
<div className="field has-addons">
|
<div className="field has-addons">
|
||||||
<p className="control">
|
<p className="control">
|
||||||
<span className="select">
|
<span className="select">
|
||||||
|
|||||||
6
src/client/hooks/store.ts
Normal file
6
src/client/hooks/store.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux";
|
||||||
|
import type { RootState, AppDispatch } from "../store";
|
||||||
|
|
||||||
|
// Use throughout your app instead of plain `useDispatch` and `useSelector`
|
||||||
|
export const useAppDispatch: () => AppDispatch = useDispatch;
|
||||||
|
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import comicinfoReducer from "../reducers/comicinfo.reducer";
|
import comicinfoReducer from "../reducers/comicinfo.reducer";
|
||||||
import fileOpsReducer from "../reducers/fileops.reducer";
|
import fileOpsReducer from "../reducers/fileops.reducer";
|
||||||
import airdcppReducer from "../reducers/airdcpp.reducer";
|
import airdcppReducer from "../reducers/airdcpp.reducer";
|
||||||
import settingsReducer from "../reducers/settings.reducer";
|
// import settingsReducer from "../reducers/settings.reducer";
|
||||||
|
|
||||||
export const reducers = {
|
export const reducers = {
|
||||||
comicInfo: comicinfoReducer,
|
comicInfo: comicinfoReducer,
|
||||||
fileOps: fileOpsReducer,
|
fileOps: fileOpsReducer,
|
||||||
airdcpp: airdcppReducer,
|
airdcpp: airdcppReducer,
|
||||||
settings: settingsReducer,
|
// settings: settingsReducer,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,57 +1,67 @@
|
|||||||
import {
|
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||||
SETTINGS_CALL_FAILED,
|
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
|
||||||
SETTINGS_OBJECT_FETCHED,
|
import { RootState } from "../store";
|
||||||
SETTINGS_OBJECT_DELETED,
|
import { isUndefined } from "lodash";
|
||||||
SETTINGS_CALL_IN_PROGRESS,
|
import { SETTINGS_SERVICE_BASE_URI } from "../constants/endpoints";
|
||||||
SETTINGS_DB_FLUSH_SUCCESS,
|
|
||||||
SETTINGS_QBITTORRENT_TORRENTS_LIST_FETCHED,
|
export interface InitialState {
|
||||||
} from "../constants/action-types";
|
data: object;
|
||||||
const initialState = {
|
inProgress: boolean;
|
||||||
|
dbFlushed: boolean;
|
||||||
|
torrentsList: Array<any>;
|
||||||
|
}
|
||||||
|
const initialState: InitialState = {
|
||||||
data: {},
|
data: {},
|
||||||
inProgress: false,
|
inProgress: false,
|
||||||
DbFlushed: false,
|
dbFlushed: false,
|
||||||
torrentsList: [],
|
torrentsList: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
function settingsReducer(state = initialState, action) {
|
export const settingsSlice = createSlice({
|
||||||
switch (action.type) {
|
name: "settings",
|
||||||
case SETTINGS_CALL_IN_PROGRESS:
|
initialState,
|
||||||
return {
|
reducers: {
|
||||||
...state,
|
SETTINGS_CALL_IN_PROGRESS: (state) => {
|
||||||
inProgress: true,
|
state.inProgress = true;
|
||||||
};
|
},
|
||||||
|
|
||||||
case SETTINGS_OBJECT_FETCHED:
|
SETTINGS_OBJECT_FETCHED: (state, action) => {
|
||||||
return {
|
state.data = action.payload;
|
||||||
...state,
|
state.inProgress = false;
|
||||||
data: action.data,
|
},
|
||||||
inProgress: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
case SETTINGS_OBJECT_DELETED:
|
SETTINGS_OBJECT_DELETED: (state, action) => {
|
||||||
return {
|
state.data = action.payload;
|
||||||
...state,
|
state.inProgress = false;
|
||||||
data: action.data,
|
},
|
||||||
inProgress: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
case SETTINGS_DB_FLUSH_SUCCESS:
|
SETTINGS_DB_FLUSH_SUCCESS: (state, action) => {
|
||||||
|
state.dbFlushed = action.payload;
|
||||||
|
state.inProgress = false;
|
||||||
|
},
|
||||||
|
|
||||||
|
SETTINGS_QBITTORRENT_TORRENTS_LIST_FETCHED: (state, action) => {
|
||||||
console.log(state);
|
console.log(state);
|
||||||
return {
|
console.log(action);
|
||||||
...state,
|
state.torrentsList = action.payload;
|
||||||
DbFlushed: action.data,
|
},
|
||||||
inProgress: false,
|
},
|
||||||
};
|
});
|
||||||
|
|
||||||
case SETTINGS_QBITTORRENT_TORRENTS_LIST_FETCHED:
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
torrentsList: action.data,
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
export const {
|
||||||
return { ...state };
|
SETTINGS_CALL_IN_PROGRESS,
|
||||||
|
SETTINGS_OBJECT_FETCHED,
|
||||||
|
SETTINGS_OBJECT_DELETED,
|
||||||
|
SETTINGS_DB_FLUSH_SUCCESS,
|
||||||
|
SETTINGS_QBITTORRENT_TORRENTS_LIST_FETCHED,
|
||||||
|
} = settingsSlice.actions;
|
||||||
|
|
||||||
|
// Other code such as selectors can use the imported `RootState` type
|
||||||
|
export const torrentsList = (state: RootState) => state.settings.torrentsList;
|
||||||
|
export const qBittorrentSettings = (state: RootState) => {
|
||||||
|
console.log(state);
|
||||||
|
if (!isUndefined(state.settings?.data?.bittorrent)) {
|
||||||
|
return state.settings?.data?.bittorrent.client.host;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
export default settingsSlice.reducer;
|
||||||
export default settingsReducer;
|
|
||||||
|
|||||||
0
src/client/services/acquisition.api.ts
Normal file
0
src/client/services/acquisition.api.ts
Normal file
7
src/client/services/empty.api.ts
Normal file
7
src/client/services/empty.api.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";
|
||||||
|
|
||||||
|
// initialize an empty api service that we'll inject endpoints into later as needed
|
||||||
|
export const emptySplitApi = createApi({
|
||||||
|
baseQuery: fetchBaseQuery({ baseUrl: "http://" }),
|
||||||
|
endpoints: () => ({}),
|
||||||
|
});
|
||||||
19
src/client/services/settings.api.ts
Normal file
19
src/client/services/settings.api.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import { emptySplitApi } from "./empty.api";
|
||||||
|
import { useConnectToQBittorrentClientQuery } from "./torrents.api";
|
||||||
|
|
||||||
|
export const settingsApi = emptySplitApi.injectEndpoints({
|
||||||
|
endpoints: (builder) => ({
|
||||||
|
getAllSettings: builder.query({
|
||||||
|
query: () => "localhost:3000/api/settings/getAllSettings",
|
||||||
|
}),
|
||||||
|
getQBitTorrentClientInfo: builder.query({
|
||||||
|
queryFn: async () => {
|
||||||
|
try {
|
||||||
|
} catch (err) {}
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
overrideExisting: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { useGetAllSettingsQuery } = settingsApi;
|
||||||
27
src/client/services/torrents.api.ts
Normal file
27
src/client/services/torrents.api.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { emptySplitApi } from "./empty.api";
|
||||||
|
|
||||||
|
export const torrentsApi = emptySplitApi.injectEndpoints({
|
||||||
|
endpoints: (builder) => ({
|
||||||
|
connectToQBittorrentClient: builder.query({
|
||||||
|
queryFn: async (_arg, _queryApi, _extraOptions, fetchWithBQ) => {
|
||||||
|
const qBittorrentHostInfo = await fetchWithBQ(
|
||||||
|
"localhost:3000/api/settings/getAllSettings",
|
||||||
|
);
|
||||||
|
await fetchWithBQ({
|
||||||
|
url: "localhost:3060/api/qbittorrent/connect",
|
||||||
|
method: "POST",
|
||||||
|
data: qBittorrentHostInfo,
|
||||||
|
});
|
||||||
|
console.log(qBittorrentHostInfo);
|
||||||
|
return {
|
||||||
|
url: "",
|
||||||
|
method: "GET",
|
||||||
|
data: qBittorrentHostInfo,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
overrideExisting: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const { useConnectToQBittorrentClientQuery } = torrentsApi;
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import { createStore, combineReducers, applyMiddleware } from "redux";
|
|
||||||
import { createHashHistory } from "history";
|
import { createHashHistory } from "history";
|
||||||
import { composeWithDevTools } from "@redux-devtools/extension";
|
|
||||||
import thunk from "redux-thunk";
|
import thunk from "redux-thunk";
|
||||||
|
import { configureStore, ThunkAction, Action } from "@reduxjs/toolkit";
|
||||||
import { createReduxHistoryContext } from "redux-first-history";
|
import { createReduxHistoryContext } from "redux-first-history";
|
||||||
import { reducers } from "../reducers/index";
|
|
||||||
import socketIoMiddleware from "redux-socket.io-middleware";
|
import socketIoMiddleware from "redux-socket.io-middleware";
|
||||||
import socketIOMiddleware from "../shared/middleware/SocketIOMiddleware";
|
import socketIOMiddleware from "../shared/middleware/SocketIOMiddleware";
|
||||||
import socketIOConnectionInstance from "../shared/socket.io/instance";
|
import socketIOConnectionInstance from "../shared/socket.io/instance";
|
||||||
|
import settingsReducer from "../reducers/settings.reducer";
|
||||||
|
import { settingsApi } from "../services/settings.api";
|
||||||
|
|
||||||
const customSocketIOMiddleware = socketIOMiddleware(socketIOConnectionInstance);
|
const customSocketIOMiddleware = socketIOMiddleware(socketIOConnectionInstance);
|
||||||
|
|
||||||
@@ -15,19 +15,30 @@ const { createReduxHistory, routerMiddleware, routerReducer } =
|
|||||||
history: createHashHistory(),
|
history: createHashHistory(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const store = createStore(
|
const rootReducer = (history) => ({
|
||||||
combineReducers({
|
settings: settingsReducer,
|
||||||
router: routerReducer,
|
[settingsApi.reducerPath]: settingsApi.reducer,
|
||||||
...reducers,
|
router: routerReducer,
|
||||||
}),
|
});
|
||||||
composeWithDevTools(
|
|
||||||
applyMiddleware(
|
const preloadedState = {};
|
||||||
socketIoMiddleware(socketIOConnectionInstance),
|
export const store = configureStore({
|
||||||
customSocketIOMiddleware,
|
middleware: [
|
||||||
thunk,
|
socketIoMiddleware(socketIOConnectionInstance),
|
||||||
routerMiddleware,
|
customSocketIOMiddleware,
|
||||||
),
|
thunk,
|
||||||
// window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(),
|
routerMiddleware,
|
||||||
),
|
settingsApi.middleware,
|
||||||
);
|
],
|
||||||
|
reducer: rootReducer(createHashHistory()),
|
||||||
|
preloadedState,
|
||||||
|
});
|
||||||
|
export type AppDispatch = typeof store.dispatch;
|
||||||
|
export type RootState = ReturnType<typeof store.getState>;
|
||||||
|
export type AppThunk<ReturnType = void> = ThunkAction<
|
||||||
|
ReturnType,
|
||||||
|
RootState,
|
||||||
|
unknown,
|
||||||
|
Action<string>
|
||||||
|
>;
|
||||||
export const history = createReduxHistory(store);
|
export const history = createReduxHistory(store);
|
||||||
|
|||||||
Reference in New Issue
Block a user