我们正在 React + Redux Toolkit + RTK Query + Webpack Module Federation + Nx 堆栈上创建一个应用程序。这个想法是将大型应用程序拆分为模块,创建一个全局存储并在模块延迟加载时用减速器填充它。
问题是加载模块时,切片没有添加到rootReucer中。
文件夹结构:
应用程序/
|--外壳/
|--退款/
库/
|--商店/
|--授权/
这是一个全局存储,假设应用程序启动时它将是空的。
export interface LazyLoadedSlices {}
export const rootReducer =
combineSlices(staticSlice).withLazyLoadedSlices<LazyLoadedSlices>();
export const dynamicMiddleware = createDynamicMiddleware();
export const store = configureStore({
devTools: process.env.ENV !== 'production',
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({ serializableCheck: false }).concat([
dynamicMiddleware.middleware,
]),
});
import { rootReducer } from '@core-backoffice/store';
export const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
addTokens: (state, { payload }: PayloadAction<PayloadLogin>) => {
const { token, refresh } = payload;
state.token = token;
state.refresh = refresh;
},
addUserData: (state, { payload }: PayloadAction<IUser>) => {
const { email, fullName, roles, userId, workspaces } = payload;
state.email = email;
state.fullName = fullName;
state.roles = roles;
state.userId = userId;
state.workspaces = workspaces;
},
logout: () => initialState,
},
selectors: {
selectToken: (state) => state.token,
selectRefreshToken: (state) => state.refresh,
},
});
declare module '@core-backoffice/store' {
export interface LazyLoadedSlices extends WithSlice<typeof authSlice> {}
}
const injectedSlice = authSlice.injectInto(rootReducer);
export const { addTokens, logout, addUserData } = injectedSlice.actions;
export const { selectRefreshToken, selectToken } = injectedSlice.selectors;
useDispatch、useSelector 和 authApi 用于 useAuth 和 useCheckAuth 钩子
export function App() {
useCheckAuth();
const location = useLocation();
const rootPath = useRootPath('/');
const token = useAppSelector((store) => store.auth?.token);
const { logout } = useAuth();
return (
<React.Suspense fallback={null}>
<Routes>
<Route path="/" element={<NxWelcome title="shell" />} />
<Route path="/moneyback/*" element={<MoneybackApp />} />
<Route path="/login" element={<LoginPage />} />
</Routes>
</React.Suspense>
);
}
export default App;
apps/moneyback/app.tsx
还使用useDispatch、useSelector和servicesApi挂钩,还使用useAuth和useCheckAuth
import { rootReducer } from '@core-backoffice/store';
import { createSlice, WithSlice } from '@reduxjs/toolkit';
const initialState: { services: string[] } = {
services: [],
};
export const servicesSlice = createSlice({
name: 'servicesSlice',
initialState,
reducers: {
addService: (state) => {
state.services = [String(Math.random())];
},
},
selectors: {
selectServices: (state) => state.services,
},
});
declare module '@core-backoffice/store' {
export interface LazyLoadedSlices extends WithSlice<typeof servicesSlice> {}
}
const injectedSlice = servicesSlice.injectInto(rootReducer);
export const { addService } = injectedSlice.actions;
export const { selectServices } = injectedSlice.selectors;
启动应用程序后,authSlcie 和 authApi 已添加到商店。
图中(image)可以看到调用了dispatch(addServices),但是store中没有切片
所有代码都是根据文档编写的 redux 工具包代码拆分
我预计切换到loclhost/moneyback后,moneyback模块将被延迟加载,并且servicesApi和servicesSlice将被添加到商店中。然而,这并没有发生。
如果您的捆绑程序以某种方式将
libs/store
捆绑在不同的捆绑包中两次,则可能会发生这种情况。
如果发生这种情况,您可以通过执行类似的操作来解决这个问题
window[Symbol.for("ReduxStore")] = window[Symbol.for("ReduxStore")] || configureStore(...)
export const store = window[Symbol.for("ReduxStore")]
在你的
libs/store