Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update array object in React Redux reducer

Tags:

This should be simple but I'm not finding the simple answer I want. I have a reducer:

const posts = (state = null, action) => {   switch(action.type){     case "PUBLISH_POST":         return state;     case "UNPUBLISH_POST":         return state;     default:         return postList;   } } 

I have a list of posts with ID's and a status. I'm sending in my post ID but can't figure out the logic to simply update the status from 0 to 1 for the item which has been clicked. I've found plenty of half-solutions but they all seem verbose and ugly - what's the shortest/best way of achieving it in this case?

Example data:

{     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  } 
like image 305
Matt Saunders Avatar asked Oct 17 '17 12:10

Matt Saunders


People also ask

How do you update an object in React Redux?

Redux: Update an Object When you want to update the top-level properties in the Redux state object, copy the existing state with ... state and then list out the properties you want to change, with their new values.

What is the best way to update an object in an array in Reactjs?

To update an object in an array in React state: Use the map() method to iterate over the array. On each iteration, check if a certain condition is met. Update the object that satisfies the condition and return all other objects as is.


2 Answers

Assuming your action is something like:

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

Simply use spread operator for it:

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;   } } 
like image 134
mersocarlin Avatar answered Sep 30 '22 07:09

mersocarlin


A more general solution, especially if state contains other data besides your posts array:

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;   } } 
like image 42
Thomas Hennes Avatar answered Sep 30 '22 09:09

Thomas Hennes