Я против этой идеи. Редуктор несет одну ответственность: обновлять состояние 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: {...}
}
Надеюсь, это поможет.