Negin
Negin

Reputation: 331

delete item in redux (functional component)

I want to delete a post by click on delete button and then go to home page (with redux in functional component) but when I click on the button it doesn't delete the post and just return to home page and show all posts.

this is my post.js component:(where I want to delete a post by click)

    import React from "react";
    import { useParams,useNavigate } from "react-router-dom";
    import { useSelector, useDispatch } from 'react-redux';
    
    const Post = () => {
      const { id } = useParams();
      const navigate = useNavigate();
      const dispatch = useDispatch();
    
      const post = useSelector(state =>
        state.posts.find(post => post.id === id)
      );
      const handleDelete=(id)=>{
        dispatch({type:'DELETE_POST',id:id});
        console.log(id)
        navigate('/');
      }
      return post ? (
        <div className="post">
          <h4 className="center">{post.title}</h4>
          <p className="center">{post.body}</p>
          <div className="center">
             <button className="btn grey" onClick={handleDelete}>Delete Post</button>
          </div>
        </div>
      ) : (<div className="center">
        "Loading post ..."
      </div>
    
      );
    };
    
    
    export default Post;

and this is my reducer:

const initState = {
  posts: [
    {
      id: "1",
      title: "Squirtle Laid an Egg",
      body: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Consequatur voluptate laborum perferendis, enim repellendus ipsam sunt autem at odit dolorum, voluptatum suscipit iste harum cum magni itaque animi laudantium fugiat",
    },
    {
      id: "2",
      title: "Charmander Laid an Egg",
      body: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Consequatur voluptate laborum perferendis, enim repellendus ipsam sunt autem at odit dolorum, voluptatum suscipit iste harum cum magni itaque animi laudantium fugiat",
    },
    {
      id: "3",
      title: "a Helix Fossil was Found",
      body: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Consequatur voluptate laborum perferendis, enim repellendus ipsam sunt autem at odit dolorum, voluptatum suscipit iste harum cum magni itaque animi laudantium fugiat",
    },
  ],
};

const rootReducer = (state = initState, action) => {
  if (action.type === "DELETE_POST") {
    let newPosts = state.posts.filter((post) => {
      return action.id !== post.id;
    });
    return {
      ...state,
      posts: newPosts,
    };
  }
  return state;
 };


export default rootReducer;

thank you for your help.

Upvotes: 1

Views: 1747

Answers (2)

Junhyunny
Junhyunny

Reputation: 884

I think the problem is same variable name in handleDelete function. Change code like this. Variable scope is polluted by event parameter "id".

    const handleDelete = (event) => {
        console.log(id)
        dispatch({type: 'DELETE_POST', id: id});
        navigate('/');
    }

And here is my full code.

App.js
import {Route, Routes, useNavigate, useParams} from "react-router-dom";
import React, {Fragment} from "react";
import {useDispatch, useSelector} from 'react-redux';

function App() {
    return (
        <Routes>
            <Route path="/" element={<Main/>}/>
            <Route path="/post/:id" element={<Post/>}/>
        </Routes>
    );
}

const Main = () => {

    const navigate = useNavigate();
    const posts = useSelector(state => state.posts);

    return (
        <div>
            <div>Main</div>
            {posts.map(post =>
                <Fragment key={post.id}>
                    <h4 className="center">{post.title}</h4>
                    <p className="center">{post.body}</p>
                </Fragment>)
            }
            <button onClick={() => navigate('/post/1')}>click me</button>
        </div>
    );
}

const Post = () => {

    const {id} = useParams();
    const navigate = useNavigate();
    const dispatch = useDispatch();

    const post = useSelector(state => {
            console.log(state)
            return state.posts.find(post => post.id === id)
        }
    );

    const handleDelete = (event) => {
        console.log(id)
        dispatch({type: 'DELETE_POST', id: id});
        navigate('/');
    }

    return post ? (
        <div className="post">
            <h4 className="center">{post.title}</h4>
            <p className="center">{post.body}</p>
            <div className="center">
                <button className="btn grey" onClick={handleDelete}>Delete Post</button>
            </div>
        </div>
    ) : (<div className="center">
            "Loading post ..."
        </div>
    );
};

export default App;
index.js
import React from 'react';
import ReactDOM from 'react-dom';

import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {BrowserRouter} from "react-router-dom";
import {Provider} from "react-redux";
import {createStore} from "redux";

const initState = {
    posts: [
        {
            id: "1",
            title: "Squirtle Laid an Egg",
            body: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Consequatur voluptate laborum perferendis, enim repellendus ipsam sunt autem at odit dolorum, voluptatum suscipit iste harum cum magni itaque animi laudantium fugiat",
        },
        {
            id: "2",
            title: "Charmander Laid an Egg",
            body: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Consequatur voluptate laborum perferendis, enim repellendus ipsam sunt autem at odit dolorum, voluptatum suscipit iste harum cum magni itaque animi laudantium fugiat",
        },
        {
            id: "3",
            title: "a Helix Fossil was Found",
            body: "Lorem ipsum, dolor sit amet consectetur adipisicing elit. Consequatur voluptate laborum perferendis, enim repellendus ipsam sunt autem at odit dolorum, voluptatum suscipit iste harum cum magni itaque animi laudantium fugiat",
        },
    ],
};

const rootReducer = (state = initState, action) => {
    if (action.type === "DELETE_POST") {
        let newPosts = state.posts.filter((post) => {
            return action.id !== post.id;
        });
        return {
            ...state,
            posts: newPosts,
        };
    }
    return state;
};

const store = createStore(rootReducer)

ReactDOM.render(
    <React.StrictMode>
        <Provider store={store}>
            <BrowserRouter>
                <App/>
            </BrowserRouter>
        </Provider>
    </React.StrictMode>,
    document.getElementById('root')
)
;

reportWebVitals();

Upvotes: 1

Drew Reese
Drew Reese

Reputation: 203587

Issue

The handleDelete handler is expecting a post id to be passed to it.

const handleDelete = (id) => {
  dispatch({ type: 'DELETE_POST', id: id });
  console.log(id)
  navigate('/');
}

But you appear to be passing the button's onClick event object instead.

<button
  className="btn grey"
  onClick={handleDelete} // <-- onClick event is passed to callback
>
  Delete Post
</button>

Solution

Use an anonymous callback function to pass the post.id to the handler.

<button
  className="btn grey"
  onClick={() => handleDelete(post.id)}
>
  Delete Post
</button>

Or convert handleDelete to a curried function to close over the post id in callback scope and return an onClick handler function.

const handleDelete = (id) => () => {
  dispatch({ type: 'DELETE_POST', id });
  console.log(id)
  navigate('/');
}

...

<button
  className="btn grey"
  onClick={handleDelete(post.id)}
>
  Delete Post
</button>

Upvotes: 1

Related Questions