假设您有两个要存储在Redux中的对象A
和B
,这些对象按照redux docs进行非规范化,如下所示:
state = {
a: { byId: { id: { obj } }, allIds: [] },
b: { byId: { id: { obj } }, allIds: [] }
};
您有一项操作,CREATE_A
会向商店添加新的A
。 但是,对于创建的每个A
,它本身也需要B
。假设A
和B
位于单独的reducer切片(即combineReducers
)中,并且不能合并为一个。
很容易让B
的reducer对CREATE_A
事件做出反应并创建一个新的B
,但如果B
对象需要A
该怎么办?刚刚创建的ID?
即使有一个join table邀请加入B
到A
,仍然存在“知道首先创建的A
”的问题。我提出的解决方案是存储最后创建的A
,如下所示:
a: { lastCreated: {}, byId: etc, allIds: etc }
然后将整个状态树传递给B
的reducer或连接表reducer,以便它可以访问state.a.lastCreated
。但是,如果只有一个键,以便以后的减速器知道发生了什么(减速器需要某种排序的想法似乎也是错误的),这感觉不对。
我认为您也可以使用新的CREATE_B
ID来发送A
,但这必须在异步操作中完成(因为您无法从reducer发送),这也感觉不对。
在程序世界中,这将是微不足道的:
a = createA();
createB(a);
但即使有两次发送,我也不确定它会如何起作用:
dispatch( createA() )
dispatch( createB(???) )
处理“A-inherently-means-B-as-well”案例的最佳方法是什么?
编辑:让我尝试使用一些更具体的例子。
假设你有square
和point
。自然地创建square
意味着创建4个point
。这些点与正方形相连,因为它们形成正方形,但它们也不属于到正方形,因为它们可以是它们自己的独立对象:
所以,ADD_SQUARE
需要添加一个正方形,并添加4个点,然后将两个加在一起,如果不直接在父“状态”中编写reducer,我不知道如何做到这一点像这样(我不想要做到这一点,它真的很乱,想象不得不重复3-8个边多边形):
function reducer(state, action) {
switch(state) {
case ADD_SQUARE:
const points = create4Points();
const square = createSquare();
return {
...state,
squares: {
...state.squares,
byId: {
...state.squares.byId
[square.id]: square
}
},
points: {
...state.points,
byId: {
...state.points.byId,
[point[0].id]: point[0],
[point[1].id]: point[1],
[point[2].id]: point[2],
[point[3].id]: point[3]
}
},
pointsSquares: {
...state.pointsSquares,
byId: {
[square.id]: {
square: square.id,
points: [point1.id, point2.id, point3.id, point4.id]
}
}
}
};
}
}
答案 0 :(得分:2)
你可以在A和B缩减器中定义相同的动作..就像这样 -
function reducerA(state, action) {
switch(action.type) {
case A_CREATE:
do A stuff
}
}
function reducerB(state, action) {
switch(action.type) {
case A_CREATE:
do B stuff
}
}
然后当你发出动作时,它会影响两个减速器。
function createA({id, stuff, etc}) {
return {
type: "A_CREATE",
payload: {id, stuff, etc}
}
}
然后你可以将id绑定到你需要创建的任何内容......从而将它们“连接”在一起。
编辑:
你可以使用redux thunk或者其他一些中间件,比如redux saga和promises来发送多个动作。
`
function handleACreation(payload) {
dispatch(
createA(payload)
.then(result => dispatch(updateB(result)))
)
}
`
显然,确切的代码不起作用 - 但总的想法仍然是:]希望这有帮助!
答案 1 :(得分:0)
就我而言,我通过在动作创建者中而不是在A
的缩减器中创建A
的ID来解决此问题。例如,
function createSquare () {
return {
type: CREATE_SQUARE,
id: newUuid()
};
}
function squareReducer ( state, action ) {
switch ( action.type ) {
case CREATE_SQUARE:
return { id: action.id };
}
}
function pointReducer ( state, action ) {
switch ( action.type ) {
case CREATE_SQUARE:
return [
{ id: newUuid(), square: action.id }
{ id: newUuid(), square: action.id } //etc
];
}
}
我仍然愿意接受其他解决方案。