Обновление объекта массива в редукторе React Redux
Это должно быть просто, но я не нахожу простого ответа, который хочу. У меня есть редуктор:
const posts = (state = null, action) => {
switch(action.type){
case "PUBLISH_POST":
return state;
case "UNPUBLISH_POST":
return state;
default:
return postList;
}
}
У меня есть список сообщений с ID
и status
, Я отправляю сообщение, но не могу понять логику, чтобы просто обновить status
от 0 до 1 для элемента, который был нажат. Я нашел множество полу-решений, но все они кажутся многословными и безобразными - каков самый короткий / лучший способ добиться этого в этом случае?
Пример данных:
{
id:1,
user:"Bob Smith",
content:"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vulputate mauris vitae diam euismod convallis. Donec dui est, suscipit at dui vitae, sagittis efficitur turpis. ",
status:1
}
4 ответа
Предполагая ваш action
это что-то вроде:
{
type: 'UNPUBLISH_POST',
payload: {
id: 1,
user: 'Bob Smith',
content: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque vulputate mauris vitae diam euismod convallis. Donec dui est, suscipit at dui vitae, sagittis efficitur turpis. ',
status: 1
}
}
Просто используйте для этого оператор распространения:
const posts = (state = null, action) => {
switch(action.type){
case "PUBLISH_POST":
case "UNPUBLISH_POST":
const index = this.state.findIndex(post => post.id === action.payload.id)
return [
...state.slice(0, index), // everything before current post
{
...state[index],
status: action.type === 'PUBLISH_POST' ? 1 : 0,
},
...state.slice(index + 1), // everything after current post
]
default:
return postList;
}
}
Более общее решение, особенно если состояние содержит другие данные, кроме вашего posts
массив:
const posts = (state = null, action) => {
const post = state.posts.find(p => p.id === action.payload.id);
switch(action.type) {
case "PUBLISH_POST":
return { ...state, posts: [ ...state.posts.filter(p => p !== post), { ...post, status: 1 } ] };
case "UNPUBLISH_POST":
return { ...state, posts: [ ...state.posts.filter(p => p !== post), { ...post, status: 0 } ] };
default:
return state;
}
}
Предполагая, что у вас есть массив сообщений, вы можете найти идентификатор сообщения, которое хотите изменить, а затем обновить его.
Ваше исходное состояние:
const initial = {
posts: [],
}
Ваш редуктор:
case MODIFY_POST:
return {
...state, //Returns the current state
posts: state.posts.map(post=> post.id === action.id ? // Loop through the array to find the post you want to modify
{ ...post, status: action.status} : post // Copy the post state and then modify it. Else return the same object.
)
}
Теперь в ваших действиях вы можете иметь два действия для переключения статуса:
export const enablePost= (post_id) => {
return {
type: MODIFY_POST,
id: post_id,
status: 1
}
}
export const disablePost= (post_id) => {
return {
type: MODIFY_POST,
id: post_id,
status: 0
}
}
Вы можете просто использовать оператор распространения в своем штате, и он автоматически обновит его так, как вы хотите.
пример:
import { GET_ALL_PENDING_DATAOPS, CHANGE_DATAOPS_ASSIGNED_TO } from "../Actions/types";
const initialState = {
requests: null
};
export default function(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case GET_ALL_PENDING_DATAOPS:
return {
...state,
requests: payload
};
case CHANGE_DATAOPS_ASSIGNED_TO:
return {
...state,
requests:payload
}
default:
return state;
}
}
Мое действие CHANGE_DATAOPS_ASSIGNED_TO отображает предыдущее состояние, в моем вызове axios я обновляю один объект запроса из массива запросов, поскольку он возвращает один объект, и я не возвращаю это явно как просто состояние, я использую распространение, он обновляет только этот объект, а остальные не трогает.