我有两个非常相似的特性(AI的“修补”和HTML画布上的“输出”)。他们每个人在应用程序中都有一个标签。修补工作良好,并正在由用户基础使用,而输出是当前的WIP。
这些特性具有几乎相同(但并非微不足道)的组件和状态,当然,我希望尽可能多地共享它们。
我有这方面的工作,但我对打字感到困惑,我也不确定这是否是解决这个问题的好办法。
这是设置:
为了共享还原器逻辑和初始状态,我将createSlice包装为createGenericCanvasSlice,根据RTK指南:https://redux-toolkit.js.org/usage/usage-with-typescript#wrapping-createslice
export const createGenericCanvasSlice = <
Reducers extends SliceCaseReducers<GenericCanvasState>
>({
name = '',
initialState,
reducers,
}: {
name: string;
initialState: GenericCanvasState;
reducers: ValidateSliceCaseReducers<GenericCanvasState, Reducers>;
}) => {
return createSlice({
name,
initialState,
reducers: {
...genericCanvasReducers, // <--- the generic reducers below
...reducers,
},
});
};一般的还原器对象如下所示:
export const genericCanvasReducers = {
setTool: (
state: GenericCanvasState,
action: PayloadAction<InpaintingTool>
) => {
state.tool = action.payload;
},
toggleTool: (state: GenericCanvasState) => {
state.tool = state.tool === 'brush' ? 'eraser' : 'brush';
},
setBrushSize: (state: GenericCanvasState, action: PayloadAction<number>) => {
state.brushSize = action.payload;
},
// etc
};然后,每个功能都会得到自己的部分,如下所示:
const inpaintingSlice = createGenericCanvasSlice({
name: 'inpainting',
initialState: initialInpaintingState as GenericCanvasState,
reducers: {
// addition reducers here if needed
},
});
const outpaintingSlice = createGenericCanvasSlice({
name: 'outpainting',
initialState: initialOutpaintingState as GenericCanvasState,
reducers: {
// addition reducers here if needed
},
});这很好;我可以为createGenericCanvasSlice创建的片分派操作,但是我必须提前知道是想要修复操作还是想要输出操作。
为了解决这个问题,我为每个泛型操作生成了块,它们接受第二个参数(当前选项卡名)。在thunk内部,检查选项卡名,并将适当的操作分派给适当的切片。
/**
* Given the two possible actions, returns a thunk that accepts a payload and tab name
* and dispatches the appropriate action to the appropriate slice.
*/
const createCanvasThunk =
(inpaintingAction, outpaintingAction) =>
(payload, activeTabName) =>
(dispatch, getState) => {
if (activeTabName === 'inpainting') {
dispatch(inpaintingAction(payload));
} else if (activeTabName === 'outpainting') {
dispatch(outpaintingAction(payload));
}
};
/**
* Creates an object with all the thunks, where the key is the action name.
*/
export const canvasThunks = _.reduce(
genericCanvasReducers,
(thunks, _action, key) => {
thunks[key] = createCanvasThunk(
inpaintingActions[key],
outpaintingActions[key]
);
return thunks;
},
{}
);这是可行的,但我无法计算出我的生命,createCanvasThunk和reduce回调的类型。
发布于 2022-11-05 09:29:02
最后,我使用了一个简单得多的解决方案。我创建了一个名为canvas的新的状态片段,并给它属性inpainting和outpainting,每个属性都有泛型画布状态的副本。
我给了canvas片另一个属性currentCanvas,即"inpainting" | "outpainting"
export interface CanvasState {
currentCanvas: ValidCanvasName;
inpainting: GenericCanvasState;
outpainting: GenericCanvasState;
}我向每个还原器添加了逻辑,以使用currentCanvas作为基本canvas片的索引,然后执行相同的逻辑。
setTool: (state, action: PayloadAction<InpaintingTool>) => {
state[state.currentCanvas].tool = action.payload;
},最后一步是更新我所有的选择器。我从新的canvasSlice导出了一个方便的选择器,以获得当前的活动画布:
export const currentCanvasSelector = (state: RootState) =>
state.canvas[state.canvas.currentCanvas];我的选择器现在看起来如下:
const inpaintingBrushSelector = createSelector(
[currentCanvasSelector, activeTabNameSelector, areHotkeysEnabledSelector],
(currentCanvas: GenericCanvasState, activeTabName, areHotkeysEnabled) => {
const { tool, brushSize, shouldShowMask } = currentCanvas;
return {
tool,
brushSize,
shouldShowMask,
activeTabName,
areHotkeysEnabled,
};
},
{
memoizeOptions: {
resultEqualityCheck: _.isEqual,
},
}
);我们可能希望将一些状态(例如画布画笔半径)从inpainting/outpainting级别提升到基本的canvas级别。然后,我们只需从适当的还原器中删除附加的currentCanvas索引。
我们可能希望在组件内部进行特殊处理,这取决于我们是在修复还是在外涂。这将通过组件中的一个简单的条件检查来处理。
因此,最终的结果是非常简单的,我们现在只需要有特殊处理的领域,其中的特点分歧。
https://stackoverflow.com/questions/74324684
复制相似问题