我有一个react项目,它有一个巨大的代码库。我使用的是redux、sagas和异步减速器。我有一个redux模块结构。有很多小的减速器,我把它们组合成几个大的异步减速器。与sagas的情况相同。
是否可以一步一步地迁移到redux工具包和rtk查询?我不能一次重写所有模块。也许有人做过同样的迁移?或者我应该保留我的样板代码库?(
这是异步冗余模块之一的代码
const reducer: (state: UserState, action: UserAction) => UserState = mergeReducers(
userReducer,
settingsReducer,
signUpReducer
);
mergeReducers函数
const mergeReducers =
(...reducers) =>
(state, action) =>
reducers.reduce((acc, reducer) => ({ ...acc, ...reducer(acc, action) }), state);
所有这些减速器都是标准减速器,如
const signUpReducer = (state: UserState = userInitialState, action: SignUpAction): UserState => {
switch (action.type) {
case SIGN_UP_CONTINUE_REQUESTED:
case SIGN_UP_INITIATE_REQUESTED:
return { ...state, pending: true, error: null };
case SIGN_UP_INITIATE_SUCCEEDED:
return { ...state, pending: false };
case SIGN_UP_CONTINUE_SUCCEEDED:
return {
...state,
profile: action.payload.profile,
token: action.payload.token,
error: null,
};
case SIGN_UP_INITIATE_REJECTED:
case SIGN_UP_CONTINUE_REJECTED:
return { ...state, pending: false, error: action.payload };
default: {
/* ::(action.type: empty) */
return { ...state };
}
}
};
此处模块的实现
function startSaga(key, saga) {
const runnableSaga = function* main() {
const sagaTask = yield fork(saga);
const { payload } = yield take(STOP_SAGA);
if (payload === key) {
yield cancel(sagaTask);
}
};
sagaMiddleware.run(runnableSaga);
}
function stopSaga(key) {
store.dispatch({
payload: key,
type: STOP_SAGA,
});
}
export const useReduxModule = (key, reducer, saga, initialAction) => {
useEffect(() => {
if (!store.asyncReducers[key]) {
store.injectReducer(key, reducer);
startSaga(key, saga);
if (initialAction) initialAction();
}
return () => {
stopSaga(key);
store.removeReducer(key);
};
}, []);
};
react中的用法。我需要在模块根组件中初始化redux模块
import { loadSomeDateRequested, reducer, saga } from './store';
const SomeComponent = ({ loadData }) => {
useReduxModule(SOME_MODULE, reducer, saga, loadData);
return (
// some jsx
);
};
export default connect(null, {
loadData: loadSomeDateRequested,
})(SomeComponent);
SomeComponent.propTypes = {
loadData: func.isRequired,
};
存储配置
function createReducer(asyncReducers) {
return combineReducers({
...staticReducers,
...asyncReducers,
});
}
export const sagaMiddleware = createSagaMiddleware();
const bindMiddleware = (middlewares) =>
(process.env.NODE_ENV !== 'production' && composeWithDevTools(applyMiddleware(...middlewares))) ||
applyMiddleware(...middlewares);
export default function configureStore() {
const store = createStore(createReducer(), bindMiddleware([sagaMiddleware]));
store.asyncReducers = {};
store.injectReducer = (key, asyncReducer) => {
store.asyncReducers[key] = asyncReducer;
store.replaceReducer(createReducer(store.asyncReducers));
};
store.removeReducer = (key) => {
delete store.asyncReducers[key];
delete store.getState()[key];
};
return store;
}
export const store = configureStore();
静态减速器为
export default {
[MODULE_PDF_MODAL]: pdfModalReducer,
};
我花了很多时间研究和阅读文档和示例。但我没有为真正的项目找到迁移的例子——只有如何迁移最简单的redux存储的例子。也许有人知道如何添加redux工具包并保持现有商店的正常工作。因为目前,我只知道一个解决方案。这个解决方案是一次重写所有的redux存储。正如我在上面所写的,我有一些异步模块,它们彼此独立。按模块迁移是现实的,但在重写它们之前,我需要保留其他模块的所有工作。
非常感谢你的回答。希望有人能帮我(
解决方案
import { configureStore } from '@reduxjs/toolkit';
import createSagaMiddleware from 'redux-saga';
import staticReducers from '@sharedStore/staticReducers';
import { combineReducers } from 'redux';
function createReducer(asyncReducers) {
return combineReducers({
...staticReducers,
...asyncReducers,
});
}
export const sagaMiddleware = createSagaMiddleware();
export default function configStore() {
const store = configureStore({
reducer: createReducer(),
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(sagaMiddleware),
});
store.asyncReducers = {};
store.injectReducer = (key, asyncReducer) => {
store.asyncReducers[key] = asyncReducer;
store.replaceReducer(createReducer(store.asyncReducers));
};
store.removeReducer = (key) => {
delete store.asyncReducers[key];
delete store.getState()[key];
};
return store;
}
export const store = configStore();
您可以使用redux工具包并保持redux,它工作稳定。对我来说,它是用于支持redux包中的组合reducers函数。
mergeReducers
。
我们的建议:将您的createStore
切换到configureStore
。这已经添加了一些辅助中间件,整个商店都将从中受益——不变性和可序列化性检查等等。然后只需将您的减速器慢慢切换到RTK——无论如何,这都是您需要触摸的减速器。随着时间的推移,您的项目将会迁移。
至于去RTK查询-这只是一个范式的改变。当然,随着时间的推移,你也可以这样做,但reducer+saga和hooks+RTKQ之间没有太多相似之处——你必须自己决定如何实现这一点。