关于减速器与动作的新手问题。 From redux documentation:
动作描述了事情发生的事实,但没有指定 应用程序的状态如何随响应而变化。
和
给定相同的参数,reducer应该计算下一个状态和 把它返还。没有惊喜。无副作用。没有API调用。没有突变。 只是一个计算。
因此,如果我们考虑以下情况:
所以我们在添加任何3+点时会产生两个副作用:
如果我将我的Point结构建模为:
// typescript
interface Point {
coordinates;
routeTo?;
}
我在动作中执行项目位置计算和路径检索是否正确,例如:
// pseudo code
export function addMapPoint(newPoint) {
return (dispatch, getState) => {
const {points} = getState();
const position = getInsertPosition(points, newPoint)
dispatch(addPoint(newPoint, position));
if (points.length >= 2) {
const previousPoint = getPreviousPoint(points, position);
calculateRoute(newPoint, previousPoint).then(route => {
dispatch(updateRoute(newPoint, route))
})
}
}
}
对我来说,这与"有些矛盾,但没有说明应用程序的状态如何变化" - 因为从动作中我指定了插入新点的位置
我可以在reducer中计算插入位置,但是我如何获取Finish点的路径数据?
这里的正确方法是什么?
答案 0 :(得分:2)
假设我们有一个calculateRoute
函数接受两个点,并返回一个解决它们之间路由的promise。
首先,让我们创建一个简单的动作创建器,以便我们知道我们的点被正确存储:
let addPoint = (point, index) => {
return {
type: 'ADD_POINT',
point: point,
index: index
}
}
然后,让我们在reducer中处理这个动作:
let reducer = (state = { points: [] }, action) => {
switch (action.type) {
case 'ADD_POINT':
return Object.assign({}, state, {
points: [
...state.points.slide(0, action.index),
action.point,
...state.points.slide(action.index + 1)
]
});
default:
return state;
}
}
现在,在用户添加一个点后,我们使用addPoint
创建一个动作并发送它,到目前为止一切都很好,但这很容易。
我努力的结构是在我的reducer中也有一个路由列表,所以让我们扩展它以支持:
let reducer = (state = { points: [], routes: [] }, action) => {
switch (action.type) {
case 'ADD_POINT':
return Object.assign({}, state, {
points: [
...state.points.slide(0, action.index),
action.point,
...state.points.slide(action.index + 1)
]
});
case 'UPDATE_ROUTES':
return Object.assign({}, state, {
routes: action.routes
});
default:
return state;
}
}
动作创建者将是:
let updateRoutes = (routes) => {
return {
type: 'UPDATE_ROUTES',
routes: routes
}
}
请注意我们正在覆盖整个路线集合。现在没关系,但可能在生产系统中你想稍微优化一下。
现在我们实际上需要编写一些逻辑。我将假设一个方便的假设,即我们有一个calculateRoutes
得到一个点集合,并返回一个解析相应路由列表的promise,每个路由将是一个对象,包含两个点和实际路由。话虽如此,我们的thunk
现在看起来像这样:
addPointAndUpdateRoutes = (point, index) => {
return (dispatch, getState) => {
// First, update the point list
dispatch(addPoint(point, index));
// Now, recalculate routes
calculateRoutes(getState().points)
.then(routes => dispatch(updateRoutes(routes));
};
};
在我看来哪种方式更好。
现在,当然,假设我们有一个神奇的calculateRoutes
函数并不是一个严肃的假设,尽管以优化的方式实现这个函数并不是一个超级难的任务(意味着实际上只向我们发送服务器的路径)之前没有计算,等等)。 但是这只是逻辑和 NOT 应用程序的状态,因此,只要您保留由商店和减少者定义的“合同”,您就可以自由实施你喜欢的任何方式。
希望这会对你有所帮助。