簡體   English   中英

我可以在動作減速器中使用條件嗎?

[英]Can I use condition in my action reducer?

基本上,在我們的例子中,我們需要獲得一個警報列表,顯示前幾個項目(首次在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
        );
    }

當我們在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);
}

無論如何在這種情況下,在reducer中使用條件語句是否可以?

我反對這個想法。 reducer有一個責任:根據操作更新Redux狀態。

以下是解決這個問題的三種方法:

簡單方法 - 將Redux狀態下的列表初始化為空列表

如果你將state列表設置為空列表( [] )那么它就更簡單了。 您基本上只需將減速器更改為:

case "GET_ALERTS":
    return {...state, list: [...state.list, action.res.data.list]

這將確保即使您已獲得要添加到列表的初始列表或更多項目,它們也將被追加。 無需添加任何邏輯 - 這是真棒恕我直言。

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]}
}

在組件我將:

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});
}

我猜你在readMorecomponentDidMount之后更新pageNum 當然,您可以將該狀態保存在Redux中並將其映射回props,並在調用getAlerts操作時將其遞增。

編寫自己的中間件

另一種方式做,這是寫的ad-hoc /功能的中間件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);
}

並更改您的reducer以簡單地將concatListconcatList狀態:

case "GET_ALERTS":
    return {...state, list: action.concatList}

此外,您必須將操作更改為包含key (在這種情況下,密鑰將設置為alert (或在redux中存儲警報狀態的密鑰的名稱)和initialList以確定是否連接。

順便說一下,把這兩個放在meta鍵下是一個好習慣。

{
  type: "GET_ALERT",
  meta: {
    initialList: true,
    key: "alert",
  },
  res: {...}
}

我希望這有幫助。

我建議你采取以下行動:

  • ALERTS / INIT - 加載初始列表
  • ALERTS / LOAD_MORE - 加載下一頁然后遞增pageNo,所以下一次調用將知道加載了多少頁
  • ALERTS / MARK_ALL_AS_READ - 服務器調用並重新初始化列表

商店結構

{
    list: [],
    currentPage: 0
}

組件代碼不應跟蹤pageNum

componentDidMount() {
    this.props.initAlerts();
}

markAllAsRead() {
   this.props.markAllAsRead();
}

readMore() {
   this.props.loadMore();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM