When I console log this.props
I get an array with post.id
and I want to make onClick
function to remove this item from the list and do not show on the page.
What is wrong with my code there?
So this is what I have:
export const deletePost = id => dispatch => {
fetch(`https://jsonplaceholder.typicode.com/posts/${id}`, {
method: "DELETE"
})
.then(res => res.json())
.then(post =>
dispatch({
type: DELETE_POST,
payload: id
}),
);
};
my reducer:
const initialState = {
items: [],
item: {}
};
case FETCH_POSTS:
return {
...state,
items: action.payload
};
case DELETE_POST:
return {
...state,
items: action.payload
};
Component contains of
const mapStateToProps = state => ({
posts: state.postsReducer.items,
});
const mapDispatchToProps = {
fetchPosts, deletePost
}
And Delete button on each post:
<button key={post.id} onClick={()=>this.props.deletePost()}>X</button>```
I'm seeing a couple of things here that you should take a look at, and hopefully they'll help you to solve your issue.
First of all, note that your deletePost
function expects a parameter with the post id. However, in the JSX code you posted for your button, you're not passing any value to the function at all. This means that the property payload
will have an undefined
value by the time the action is dispatched.
Make sure you update your view to pass it an id, so you call the proper endpoint (your DELETE
request is probably pointing to https://jsonplaceholder.typicode.com/posts/undefined
right now) and the reducer actually receives the id of the post you want to remove:
<button key={post.id} onClick={()=>this.props.deletePost(post.id)}>X</button>
The second thing you have to check is the implementation of your reducer. From what I've understood in your message and the code for the deletePost
method, action.payload
should contain a number.
That being the case, how your reducer is handling the DELETE_POST
action in the reducer doesn't make too much sense to me.
case DELETE_POST:
return {
...state,
items: action.payload
};
Reducers are supposed to be pure functions that, for a given state and action, returns an entirely new state based on the action it receives. Remember too that the state you receive cannot be altered at all: if the original instance is mutated in any way, your code will not work.
In this case, you need to return a new state where your items
property is replaced by a new list where the id you want to remove is missing. In the piece of code you wrote, however, you're replacing the items
array by a number. This is not what was supposed to happen, starting by the fact that items
should still be an array of numbers.
What you actually need to do is to create a new array that does not include the item you wanted to remove. You may use the filter
method to achieve this:
case DELETE_POST:
return {
...state,
items: state.items.filter(item => item !== action.payload)
};
This code should do exactly what you want: here we are assigning the items
property in your state an entirely new array where the deleted post is not included.
filter
returns an array with the items for which the specified function returns true
. In this case, the arrow function we're passing to filter
returns true
for every item that's different from the id of the post you want to remove.
By using this method you will also have no problems with the initial state.items
value being mutated somehow, as filter
returns a new instance of Array
and does not alter the original.