如果我以这种方式为异步操作设计减速器,我会 运行 遇到什么问题?
In what problems will I run if I design my reducers for async actions this way?
我在创建前端应用程序方面经验很少,想在使用 Redux 时为自己建立一些约定。
目前我的异步操作减速器是这样的:
const initialState = {
isRunning: false,
isFinished: false,
hasError: false,
response: null
};
export const updatePostReducer = (state = initialState, action=null) => {
switch (action.type) {
case UPDATE_POST:
return {
isRunning: true,
isFinished: false,
hasError: false,
response: null
};
break;
case UPDATE_POST_SUCCESS:
return {
isRunning: false,
isFinished: true,
hasError: false,
response: action.payload
};
break;
case UPDATE_POST_ERROR:
return {
isRunning: false,
isFinished: false,
hasError: true,
response: null,
statusCode: action.statusCode
};
case UPDATE_POST_INVALIDATE:
return initialState;
break;
default:
return state;
}
};
上面的方法没有问题,但我发现 "process stages" 令人困惑。因此我的想法是将其缩短为:
// IMPORTED FROM SEPARATE FILE
const stage = {
INITIAL: "INITIAL",
RUNNING: "RUNNING",
FINISHED: "FINISHED",
ERROR: "ERROR"
};
const initialState = {
stage: stage.INITIAL,
response: null
};
export const updatePostReducer = (state = initialState, action=null) => {
switch (action.type) {
case UPDATE_POST:
return {
stage: stage.RUNNING,
response: null
};
case UPDATE_POST_SUCCESS:
return {
stage: stage.FINISHED,
response: action.payload
};
case UPDATE_POST_ERROR:
return {
stage: stage.ERROR,
response: null,
statusCode: action.statusCode
};
case UPDATE_POST_INVALIDATE:
return initialState;
default:
return state;
}
};
我看到使用后一种方法有 2 个优点:
- 更干净
- 可以使用 switch() 而不是肮脏的 if-elses
缺点是:
- 这需要在所有地方导入 stages.js。
- 阶段没有细粒度控制
我的问题是:由于没有对stage进行细粒度的控制,在某些场景下会不会出现问题?例如,是否存在需要同时具有 hasError=true, isRunning=true
的情况?
如果不知道您的应用程序的用例,您提出的问题很难回答。但是,如果这不是一个非常简单的问题,我会说您可能 运行 通过这种简化迟早会遇到问题。
我也看到一些非初始化值的问题,比如 statusCode
。顺便说一句,其他州没有更新。如果出错时更新了代码,重试成功后还是一样。
我会提出另一种方式,使用 combineReducers()
更加明确。
方法如下:
const isRunningReducer = (state=false, action=null) => {
switch (action.type) {
case UPDATE_POST:
return true;
case UPDATE_POST_SUCCESS:
return false;
case UPDATE_POST_ERROR:
return false;
case UPDATE_POST_INVALIDATE:
return false;
default:
return state;
}
};
const isFinishedReducer = (state=false, action=null) => {
switch (action.type) {
case UPDATE_POST:
return false;
case UPDATE_POST_SUCCESS:
return true;
case UPDATE_POST_ERROR:
return false;
case UPDATE_POST_INVALIDATE:
return false;
default:
return state;
}
};
const hasErrorReducer = (state=false, action=null) => {
switch (action.type) {
case UPDATE_POST:
return false;
case UPDATE_POST_SUCCESS:
return false;
case UPDATE_POST_ERROR:
return true;
case UPDATE_POST_INVALIDATE:
return false;
default:
return state;
}
};
const statusCodeReducer = (state=null, action=null) => {
switch (action.type) {
case UPDATE_POST:
return null;
case UPDATE_POST_SUCCESS:
return action.statusCode;
case UPDATE_POST_ERROR:
return action.statusCode;
case UPDATE_POST_INVALIDATE:
return null;
default:
return state;
}
};
const responseReducer = (state=null, action=null) => {
switch (action.type) {
case UPDATE_POST:
return null;
case UPDATE_POST_SUCCESS:
return action.payload;
case UPDATE_POST_ERROR:
return null;
case UPDATE_POST_INVALIDATE:
return null;
default:
return state;
}
};
export const updatePostReducer = combineReducers({
isRunningReducer,
isFinishedReducer,
hasErrorReducer,
statusCodeReducer,
responseReducer,
});
缺点:
- 更详细
- 重复
优点:
- 非常简单易懂的减速器
- 不易出错
- 易于扩展
- 易于编写生成器代码,以便可以导入 "isRunning"、"isFinished" 等标准减速器
所有这些都可以使用自己的 createReducer()
方法变得更加优雅,如下所述:Reducing Boilerplate - Generating Reducers
我在创建前端应用程序方面经验很少,想在使用 Redux 时为自己建立一些约定。
目前我的异步操作减速器是这样的:
const initialState = {
isRunning: false,
isFinished: false,
hasError: false,
response: null
};
export const updatePostReducer = (state = initialState, action=null) => {
switch (action.type) {
case UPDATE_POST:
return {
isRunning: true,
isFinished: false,
hasError: false,
response: null
};
break;
case UPDATE_POST_SUCCESS:
return {
isRunning: false,
isFinished: true,
hasError: false,
response: action.payload
};
break;
case UPDATE_POST_ERROR:
return {
isRunning: false,
isFinished: false,
hasError: true,
response: null,
statusCode: action.statusCode
};
case UPDATE_POST_INVALIDATE:
return initialState;
break;
default:
return state;
}
};
上面的方法没有问题,但我发现 "process stages" 令人困惑。因此我的想法是将其缩短为:
// IMPORTED FROM SEPARATE FILE
const stage = {
INITIAL: "INITIAL",
RUNNING: "RUNNING",
FINISHED: "FINISHED",
ERROR: "ERROR"
};
const initialState = {
stage: stage.INITIAL,
response: null
};
export const updatePostReducer = (state = initialState, action=null) => {
switch (action.type) {
case UPDATE_POST:
return {
stage: stage.RUNNING,
response: null
};
case UPDATE_POST_SUCCESS:
return {
stage: stage.FINISHED,
response: action.payload
};
case UPDATE_POST_ERROR:
return {
stage: stage.ERROR,
response: null,
statusCode: action.statusCode
};
case UPDATE_POST_INVALIDATE:
return initialState;
default:
return state;
}
};
我看到使用后一种方法有 2 个优点:
- 更干净
- 可以使用 switch() 而不是肮脏的 if-elses
缺点是:
- 这需要在所有地方导入 stages.js。
- 阶段没有细粒度控制
我的问题是:由于没有对stage进行细粒度的控制,在某些场景下会不会出现问题?例如,是否存在需要同时具有 hasError=true, isRunning=true
的情况?
如果不知道您的应用程序的用例,您提出的问题很难回答。但是,如果这不是一个非常简单的问题,我会说您可能 运行 通过这种简化迟早会遇到问题。
我也看到一些非初始化值的问题,比如 statusCode
。顺便说一句,其他州没有更新。如果出错时更新了代码,重试成功后还是一样。
我会提出另一种方式,使用 combineReducers()
更加明确。
方法如下:
const isRunningReducer = (state=false, action=null) => {
switch (action.type) {
case UPDATE_POST:
return true;
case UPDATE_POST_SUCCESS:
return false;
case UPDATE_POST_ERROR:
return false;
case UPDATE_POST_INVALIDATE:
return false;
default:
return state;
}
};
const isFinishedReducer = (state=false, action=null) => {
switch (action.type) {
case UPDATE_POST:
return false;
case UPDATE_POST_SUCCESS:
return true;
case UPDATE_POST_ERROR:
return false;
case UPDATE_POST_INVALIDATE:
return false;
default:
return state;
}
};
const hasErrorReducer = (state=false, action=null) => {
switch (action.type) {
case UPDATE_POST:
return false;
case UPDATE_POST_SUCCESS:
return false;
case UPDATE_POST_ERROR:
return true;
case UPDATE_POST_INVALIDATE:
return false;
default:
return state;
}
};
const statusCodeReducer = (state=null, action=null) => {
switch (action.type) {
case UPDATE_POST:
return null;
case UPDATE_POST_SUCCESS:
return action.statusCode;
case UPDATE_POST_ERROR:
return action.statusCode;
case UPDATE_POST_INVALIDATE:
return null;
default:
return state;
}
};
const responseReducer = (state=null, action=null) => {
switch (action.type) {
case UPDATE_POST:
return null;
case UPDATE_POST_SUCCESS:
return action.payload;
case UPDATE_POST_ERROR:
return null;
case UPDATE_POST_INVALIDATE:
return null;
default:
return state;
}
};
export const updatePostReducer = combineReducers({
isRunningReducer,
isFinishedReducer,
hasErrorReducer,
statusCodeReducer,
responseReducer,
});
缺点:
- 更详细
- 重复
优点:
- 非常简单易懂的减速器
- 不易出错
- 易于扩展
- 易于编写生成器代码,以便可以导入 "isRunning"、"isFinished" 等标准减速器
所有这些都可以使用自己的 createReducer()
方法变得更加优雅,如下所述:Reducing Boilerplate - Generating Reducers