我可以在动作减速器中使用条件吗?

cat*_*use 3 javascript reactjs redux

基本上,在我们的例子中,我们需要获得一个警报列表,显示前几个项目(首次在DOM中安装)或显示初始列表+下一个列表(单击load more按钮).

因此我们需要在GET_ALERTS行动中做到这一点:

case "GET_ALERTS":
    if (action.initialList) {
        newState.list = [...newState.list, action.res.data.list];
    } else {
        newState.list = newState.list.concat(
            action.res.data.list
        );
    }
Run Code Online (Sandbox Code Playgroud)

当我们在Alerts组件中调用action reducer时,我们需要指出initialList是true还是false.

例如

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);
}
Run Code Online (Sandbox Code Playgroud)

无论如何在这种情况下,在reducer中使用条件语句是否可以?

boa*_*ter 5

我反对这个想法.reducer有一个责任:根据操作更新Redux状态.

以下是解决这个问题的三种方法:

简单方法 - 将Redux状态下的列表初始化为空列表

如果你将列表设置state为空列表([])然后它更简单.您基本上只需将减速器更改为:

case "GET_ALERTS":
    return {...state, list: [...state.list, action.res.data.list]
Run Code Online (Sandbox Code Playgroud)

这将确保即使您已获得要添加到列表的初始列表或更多项目,它们也将被追加.无需添加任何逻辑 - 这是真棒恕我直言.

redux-thunk和分离类型分为两种不同的类型

创建两个动作:GET_INIT_ALERTSGET_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]}
}
Run Code Online (Sandbox Code Playgroud)

在组件我将:

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);
}
Run Code Online (Sandbox Code Playgroud)

在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});
}
Run Code Online (Sandbox Code Playgroud)

我想你更新pageNumreadMorecomponentDidMount.当然,您可以将该状态保存在Redux中并将其映射回道具,并在调用getAlerts操作时将其递增.

编写自己的中间件

另一种方法是将ad-hoc/feature中间件写入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);
}
Run Code Online (Sandbox Code Playgroud)

并改变你的减速器,只需推动concatList状态:

case "GET_ALERTS":
    return {...state, list: action.concatList}
Run Code Online (Sandbox Code Playgroud)

此外,您必须将操作更改为包含key(在这种情况下,密钥将设置为alert(或在redux中存储警报状态的密钥的名称)和initialList以确定是否连接.

顺便说一下,将这两者置于meta关键之下是一种很好的做法.

{
  type: "GET_ALERT",
  meta: {
    initialList: true,
    key: "alert",
  },
  res: {...}
}
Run Code Online (Sandbox Code Playgroud)

我希望这有帮助.