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 }
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.
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.
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; } }
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; } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With