javascript - Can I use condition in my action reducer?
问题描述
Basically, in our case, we need to either get an alerts list that shows the first few items (mounting it first time in the DOM) or show the initial list + the next list (clicking a load more
button).
Hence we needed to do this condition in our GET_ALERTS
action:
case "GET_ALERTS":
if (action.initialList) {
newState.list = [...newState.list, action.res.data.list];
} else {
newState.list = newState.list.concat(
action.res.data.list
);
}
And when we call the action reducer in our Alerts component, we need to indicate whether initialList
is true or false.
E.g.
componentDidMount() {
this.props.getAlerts(pageNum, true);
}
markAllAsRead() {
// other code calling api to mark all as read
this.props.getAlerts(pageNum, false);
}
readMore() {
// other code that increases pageNum state counter
this.props.getAlerts(pageNum, true);
}
Anyway in such a case, is it fine to use conditional statement in the reducer?
解决方案
我反对这个想法。reducer 的职责只有一个:根据 action 更新 Redux 状态。
以下是解决此问题的三种方法:
简单的方法 - 将 Redux 状态下的列表初始化为空列表
如果您将列表设置state
为空列表([]
),那么它会简单得多。您基本上可以将减速器更改为:
case "GET_ALERTS":
return {...state, list: [...state.list, action.res.data.list]
这将确保即使您有初始列表或更多要添加到列表中的项目,它们也会被附加。无需添加任何逻辑 - 恕我直言,这很棒。
redux-thunk 和分离类型成两种不同的类型
创建两个动作:GET_INIT_ALERTS
和GET_MORE_ALERTS
。
switch(action.type) {
case "GET_INIT_ALERTS":
return {...state, list: action.res.data.list }
case "GET_MORE_ALERTS":
return {...state, list: [...state.list, ...action.res.data.list]}
case "CHECK_READ_ALERTS":
return {...state, read: [...state.read, ...action.res.data.list]}
}
在组件中,我将拥有:
componentDidMount() {
this.props.getInitAlerts();
}
markAllAsRead() {
// other code calling api to mark all as read
this.props.getAlerts(pageNum, false);
}
readMore() {
// other code that increases pageNum state counter
this.props.getAlerts(pageNum);
}
在 redux-thunk 的帮助下进行警报操作:
export const getAlerts = (pageNum : number) => (dispatch) => {
return apiAction(`/alerts/${pageNum}`, 'GET').then(res => dispatch({type: "GET_MORE_ALERTS", res});
}
export const getInitAlerts = () => (dispatch) => {
return apiAction('/alerts/1', 'GET').then(res => dispatch({type: "GET_INIT_ALERTS", res});
}
我猜你在orpageNum
之后更新。当然,您可以在 Redux 中保存该状态并将其映射回 props,并在调用操作时将其递增。readMore
componentDidMount
getAlerts
编写自己的中间件
另一种方法是将临时/功能中间件写入concat
列表中的新数据。
const concatLists = store => next => action => {
let newAction = action
if (action.type.includes("GET") && action.initialList) {
newAction = {...action, concatList: action.res.data.list}
} else if (action.type.includes("GET") {
newAction = {...action, concatList: [...state[action.key].list, action.res.data.list]}
}
return next(newAction);
}
并将您的减速器更改为简单地推concatList
送到状态:
case "GET_ALERTS":
return {...state, list: action.concatList}
此外,您必须更改您的操作以包括key
(在这种情况下,键将设置为alert
(或您在 redux 中存储警报状态的键的名称)和 initialList 以确定是否连接。
顺便说一句,将这两个放在meta
关键位置是一个好习惯。
{
type: "GET_ALERT",
meta: {
initialList: true,
key: "alert",
},
res: {...}
}
我希望这有帮助。
推荐阅读
- java - java的Scala编译器
- visual-studio - 如何从 VScode 工作区中删除目录而不从操作系统文件结构中删除它?
- c# - 在 excel 中读取自定义数据类型的 excel 数据以加载到数据集中,但它正在使用 oledb 提供程序截断十进制值
- java - 如何在应用程序中仅在特定时间段内启用某些功能?
- php - 在移动设备上切换显示/隐藏配置 - ACF 中继器
- apache-kafka - 如果删除 Kafka 快照文件会发生什么?
- java - 我可以使用类 Timer 将日期传递给方法 scheduleAtFixedRate 吗?
- sql - SSRS 和 SQL NTILE 不接受参数?
- image - 如何在 aws s3 上浏览图像
- windows - Add-Content、Start-Transcript 和 Remove-Item 在通过任务启动时不起作用