Могу ли я использовать условие в моем редукторе действия? - PullRequest
0 голосов
/ 30 октября 2018

По сути, в нашем случае нам нужно либо получить список предупреждений, который показывает первые несколько элементов (монтирует его в первый раз в 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, нам нужно указать, является ли initialList истинным или ложным.

например.

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

В любом случае, в таком случае нормально использовать условное выражение в редукторе?

Ответы [ 2 ]

0 голосов
/ 07 ноября 2018

Я бы предложил вам выполнить следующие действия:

  • 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();
}
0 голосов
/ 30 октября 2018

Я против этой идеи. Редуктор несет одну ответственность: обновлять состояние Redux в соответствии с действием.

Вот три способа решить эту проблему:

простой способ - инициализировать ваш список в состоянии Redux пустым списком

если вы установите список в state в пустой список ([]), тогда это будет намного проще. Вы можете просто изменить свой редуктор на это:

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

Это гарантирует, что даже если у вас есть начальный список или несколько элементов для добавления в список, они будут добавлены. Не нужно добавлять какую-либо логику - это потрясающе ИМХО.

избыточный и разделительный тип на два разных типа

создать два действия: 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});
}

Я полагаю, вы обновляете pageNum после readMore или componentDidMount. Конечно, вы можете сохранить это состояние в Redux, отобразить его обратно в подпорки и просто увеличить его при вызове действия 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 (или имя ключа, в котором вы сохраняете состояние оповещения в избыточном коде), а initialList - на определить, следует ли примирить или нет.

Кстати, это хорошая практика - ставить их под клавишу meta.

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

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...