使用Redux Toolkit中的createSlice动态加载initialState



是否有一种众所周知的模式可以将动态初始状态的有效负载注入Redux Toolkit的initialState对象?

也就是说,我想做这个-

import initialState from './initialState';
function generateSlice(payload = {}){
const postsSlice = createSlice({
name: 'posts',
initialState: {...initialState, ...payload}, /// inject data here
reducers: {...}
})
}

例如,{availableRooms: []}是一个空数组,除非在init中注入数据{availableRooms: [{...}]}

然而,这种模式不起作用,b/c我希望导出可调度的操作,类似于这样的东西-

const postsSlice = createSlice({
name: 'posts',
initialState: {...initialState, ...payload},
reducers: {...}
})
export {actionName} from postsSlice.actions;
*****
import {actionName} from '../mySlice'
...
const dispatch = useDispatch();
dispatch(actionName('exampleVal'));
...

我受到airbnblinting规则的约束,所以我不能在let-上导出

let actions; ///Bad
function generateSlice(payload){
const postsSlice = createSlice({
name: 'posts',
initialState: {...initialState, ...payload},
reducers: {...}
})
actions = postsSlict.actions
}
export actions;

如果不使用createSlice,我所追求的功能会简单一些。我提出这个问题的原因是,我在多个地方看到createSlicecreateAction+createReducer更受推荐,但我看不到任何简单的方法来介绍我正在寻找的动态数据。

我对redux-orm一无所知,但我认为我所追求的功能与这个SO问题相似

这是我目前的工作,它完全跳过了createSlice

在根渲染中

...
const store = initStore(data);
<Provider store={store}>
<App />
</Provider>

和init函数(为简洁起见,进行了精简(

import {
configureStore,
getDefaultMiddleware,
combineReducers,
} from '@reduxjs/toolkit';
import reservationReducer from '@reservation/reducer';
import spaceHierarchyReducer from '@map/reducer';
import appStoreReducer from '@app/reducer';
let ReduxStore;
function initStore(
ssrState: Partial<RootStore> = {},
) {
if (ReduxStore) {
return ReduxStore;
}
const slices = {
reservation: reservationReducer,
spaceHierarchy: spaceHierarchyReducer,
appStore: appStoreReducer,
};
const reducer = combineReducers(slices);
const preloadedState = getInitialState(ssrState);
const store = configureStore({
reducer,
middleware,
preloadedState,
});
ReduxStore = store;
initDispatch(store);
return store;
}

getInitialState中,我解析URL并根据业务需求设置存储,这是服务器端数据+URL可注入参数的混合。然后,在initDispatch中,我为一些基于注入初始状态的初始化逻辑调用store.dispatch()

在这里,Typescript的使用非常有用,因为它强制执行从getInitialState返回的数据的形状以及减速器的形状。

我找到了一个使用Redux工具包的解决方案。我对Redux有点陌生,因为Context API不能重新发送React Native Navigation Screens,因为它们不是主树的一部分。我不知道我的方法是否足够好,但我的想法是:

  • generateSlice()不会填充操作变量,因为在RTK模块使用导出时,尚未调用generateSlice
  • RTK模块一开始只需要createSlice的结构和配置,但还不需要存储对象。只有configureStore真正关心商店本身。因此,使用重复调用:导出具有正常默认initialState的操作,然后在generateSlice(initValue)中调用具有实际默认initialValue的操作似乎效果良好

为了让每个人都更简单,我举了一个RTK官方简短教程的例子https://redux-toolkit.js.org/tutorials/quick-start:

counterSlice.js:

import { createSlice } from '@reduxjs/toolkit';
const initialState = {
value: 0,
};
const slicer = initState =>
createSlice({
name: 'counter',
initialState: initState,
reducers: {
increment: state => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
// doesn't actually mutate the state because it uses the Immer library,
// which detects changes to a "draft state" and produces a brand new
// immutable state based off those changes
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
const generateSlice = initState => {
return slicer(initState).reducer;
};
export const counter = slicer(initialState);
// Action creators are generated for each case reducer function
export const { increment, decrement, incrementByAmount } = counter.actions;
export default generateSlice;

store.js现在成为一个函数,必要时将其重命名为getStore

import { configureStore } from '@reduxjs/toolkit';
import generateCounterReducer from '../states/reducers/counter';
export const store = states => {
return configureStore({
reducer: {
counter: generateCounterReducer(states.counter),
},
});
};

App.jsindex.js将redux提供程序放在何处:

<Provider
store={store({
counter: { value: 7 },
})}
>

当我加载组件时,默认情况下会渲染值7。它唯一的问题是它执行createSlice2次。但由于这种情况只发生在应用程序启动时,因此我认为这种方法没有性能问题。也许这种模式会与高级使用相冲突,所以如果有人看到任何瓶颈,我们可以讨论并找出如何改进它

最新更新