showing/hiding 加载屏幕之类的操作应该由 reducer 处理相关操作,还是由操作创建者自己生成?
Should actions like showing/hiding loading screens be handled by reducers to related actions or generated by action creators themselves?
鉴于您可能希望在许多情况下出现一些全局视图(例如显示加载屏幕),为该行为创建一个操作 creator/action 对更合适还是相关操作的减速器是否处理转换?
这很难简洁地描述,为了说明我的意思,这里有几个例子。哪个更好,为什么?
一个
function showLoading () {
return 'SHOW_LOADING';
}
function hideLoading () {
return 'HIDE_LOADING';
}
function fetchPostsRequest () {
return 'FETCH_POSTS_REQUEST';
}
function fetchPostsSuccess () {
return 'FETCH_POSTS_SUCCESS';
}
function doSomethingAsync () {
return dispatch => {
dispatch(showLoading());
dispatch(fetchPostsRequest());
// other logic
dispatch(hideLoading())
dispatch(fetchPostsSuccess());
}
}
function rootReducer (state = {}, action) {
const payload = action.payload;
switch(action) {
case 'SHOW_LOADING':
Object.assign({}, state, {isLoading: true})
break;
case 'HIDE_LOADING':
Object.assign({}, state, {isLoading: false})
break;
// other reducers for handling success/request stuff
}
}
B
function fetchPostsRequest () {
return 'FETCH_POSTS_REQUEST';
}
function fetchPostsSuccess () {
return 'FETCH_POSTS_SUCCESS';
}
function fetchPostsFailure () {
return 'FETCH_POSTS_FAILURE';
}
function doSomethingAsync () {
return dispatch => {
dispatch(fetchPostsRequest());
// good
dispatch(fetchPostsSuccess());
// bad
dispatch(fetchPostsFailure());
}
}
function rootReducer (state = {}, action) {
const payload = action.payload;
switch(action) {
case 'FETCH_POSTS_REQUEST':
Object.assign({}, state, {isLoading: true})
break;
case 'FETCH_POSTS_SUCCESS':
Object.assign({}, state, {isLoading: false /* other logic */})
break;
case 'FETCH_POSTS_FAILURE':
Object.assign({}, state, {isLoading: false /* other logic */})
break;
}
}
我更喜欢A,因为在我看来,在一个地方描述这些行为比复制状态管理的逻辑更明智,但我在redux社区听到过一个格言,即动作应该描述发生或正在发生的事情,而不是命令式命令。在这种情况下,这只是一个语义问题吗?"ASYNC_OPERATION_START" 比 "SHOW_LOADING" 更好?
想想这段代码将如何演变。
用它来做决定。
例如,您可能有不止一组可以加载的项目。您最终可能会有两个并排的项目列表,或者一个在另一个下面。因此,您将希望它们具有单独的 isLoading
状态,就像它们具有单独的 ID 列表一样。
这两个选项中的代码将如何变化?似乎拥有更少的动作更简单,因为这可以让您保持特定列表的 isLoading
状态接近关于它的其他信息,而且不用担心您忘记在动作创建者中重置它的状态。所以在这种情况下我会选择选项 B.
另一方面,如果我们讨论的是显示 UI 通知这样的用例,我可能会将其作为单独的操作触发。它的存在完全独立于引起它的服务器响应:通知需要在一段时间后隐藏,两个通知可能同时出现在屏幕上,等等。因此,对于这个用例,选项 A 似乎更合适。
一般来说,你应该问自己:
- 这段代码可能会如何演变?
- 这两个动作真的是同一个还是它们只是相关但独立?
鉴于您可能希望在许多情况下出现一些全局视图(例如显示加载屏幕),为该行为创建一个操作 creator/action 对更合适还是相关操作的减速器是否处理转换?
这很难简洁地描述,为了说明我的意思,这里有几个例子。哪个更好,为什么?
一个
function showLoading () {
return 'SHOW_LOADING';
}
function hideLoading () {
return 'HIDE_LOADING';
}
function fetchPostsRequest () {
return 'FETCH_POSTS_REQUEST';
}
function fetchPostsSuccess () {
return 'FETCH_POSTS_SUCCESS';
}
function doSomethingAsync () {
return dispatch => {
dispatch(showLoading());
dispatch(fetchPostsRequest());
// other logic
dispatch(hideLoading())
dispatch(fetchPostsSuccess());
}
}
function rootReducer (state = {}, action) {
const payload = action.payload;
switch(action) {
case 'SHOW_LOADING':
Object.assign({}, state, {isLoading: true})
break;
case 'HIDE_LOADING':
Object.assign({}, state, {isLoading: false})
break;
// other reducers for handling success/request stuff
}
}
B
function fetchPostsRequest () {
return 'FETCH_POSTS_REQUEST';
}
function fetchPostsSuccess () {
return 'FETCH_POSTS_SUCCESS';
}
function fetchPostsFailure () {
return 'FETCH_POSTS_FAILURE';
}
function doSomethingAsync () {
return dispatch => {
dispatch(fetchPostsRequest());
// good
dispatch(fetchPostsSuccess());
// bad
dispatch(fetchPostsFailure());
}
}
function rootReducer (state = {}, action) {
const payload = action.payload;
switch(action) {
case 'FETCH_POSTS_REQUEST':
Object.assign({}, state, {isLoading: true})
break;
case 'FETCH_POSTS_SUCCESS':
Object.assign({}, state, {isLoading: false /* other logic */})
break;
case 'FETCH_POSTS_FAILURE':
Object.assign({}, state, {isLoading: false /* other logic */})
break;
}
}
我更喜欢A,因为在我看来,在一个地方描述这些行为比复制状态管理的逻辑更明智,但我在redux社区听到过一个格言,即动作应该描述发生或正在发生的事情,而不是命令式命令。在这种情况下,这只是一个语义问题吗?"ASYNC_OPERATION_START" 比 "SHOW_LOADING" 更好?
想想这段代码将如何演变。
用它来做决定。
例如,您可能有不止一组可以加载的项目。您最终可能会有两个并排的项目列表,或者一个在另一个下面。因此,您将希望它们具有单独的 isLoading
状态,就像它们具有单独的 ID 列表一样。
这两个选项中的代码将如何变化?似乎拥有更少的动作更简单,因为这可以让您保持特定列表的 isLoading
状态接近关于它的其他信息,而且不用担心您忘记在动作创建者中重置它的状态。所以在这种情况下我会选择选项 B.
另一方面,如果我们讨论的是显示 UI 通知这样的用例,我可能会将其作为单独的操作触发。它的存在完全独立于引起它的服务器响应:通知需要在一段时间后隐藏,两个通知可能同时出现在屏幕上,等等。因此,对于这个用例,选项 A 似乎更合适。
一般来说,你应该问自己:
- 这段代码可能会如何演变?
- 这两个动作真的是同一个还是它们只是相关但独立?