关于减速器与动作的新手问题。来自 redux 文档:
\n\n\n\n\n操作描述了发生了某些事情的事实,但不指定应用程序状态如何更改以响应。
\n
和
\n\n\n\n\n给定相同的参数,reducer 应该计算下一个状态并返回它。没有什么惊喜。无副作用。没有 API 调用。没有突变。\n 只是一个计算。
\n
因此,如果我们考虑以下场景:
\n\n因此,在添加任何 3 个以上的点时,我们会产生两个副作用:
\n\n如果我将我的 Point 结构建模如下:
\n\n // typescript\ninterface Point {\n coordinates;\n routeTo?;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n我在操作中执行项目位置计算和路线检索是否正确,例如:
\n\n // pseudo code\n export function addMapPoint(newPoint) {\n return (dispatch, getState) => {\n const {points} = getState();\n const position = getInsertPosition(points, newPoint)\n dispatch(addPoint(newPoint, position));\n if (points.length >= 2) {\n const previousPoint = getPreviousPoint(points, position);\n calculateRoute(newPoint, previousPoint).then(route => {\n dispatch(updateRoute(newPoint, route))\n })\n }\n }\n }\nRun Code Online (Sandbox Code Playgroud)\n\n对我来说,这在某种程度上与“但不要指定应用程序 xe2x80x99s 状态如何更改”相矛盾 - 因为从操作中我指定了在哪里插入新点。
\n我可以计算reducer中的插入位置,但是如何获取终点的路线数据?
\n这里正确的方法是什么?
假设我们有一个calculateRoute接受两个点的函数,并返回一个解决它们之间路线的承诺。
首先,让我们创建一个简单的动作创建器,以便我们知道我们的点已正确存储:
let addPoint = (point, index) => {
return {
type: 'ADD_POINT',
point: point,
index: index
}
}
Run Code Online (Sandbox Code Playgroud)
然后,让我们在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;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,在用户添加一个点后,我们使用addPoint并分派它创建一个操作,到目前为止一切顺利,但这是简单的事情。
我追求的结构是在我的减速器中也有一个路由列表,所以让我们扩展它以支持这一点:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
动作创建者将是:
let updateRoutes = (routes) => {
return {
type: 'UPDATE_ROUTES',
routes: routes
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我们将覆盖整个路线集合。目前还可以,但在生产系统中您可能需要对其进行一些优化。
现在我们实际上需要编写一些逻辑。我将假设一个方便的假设,即我们有一个calculateRoutes获取点的集合,并返回一个解析相应路线列表的承诺,每个路线将是一个对象,包含两个点和实际路线。话虽如此,我们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));
};
};
Run Code Online (Sandbox Code Playgroud)
我认为这更好。
当然,假设我们有一个神奇的calculateRoutes功能并不是一个严肃的假设,尽管以优化的方式实现这个功能并不是一个超级困难的任务(意味着实际上只向服务器发送我们之前没有计算过的路由等)。但这只是逻辑,而不是应用程序的状态,因此,只要您保留存储和减速器定义的“契约”,您就可以自由地以任何您喜欢的方式实现它。
希望这对您有帮助。
| 归档时间: |
|
| 查看次数: |
4040 次 |
| 最近记录: |