1

I'm in the midst of making a facebook clone. One of the main components of this site, is a feed that contains a list of posts. These posts are coming from the databse and are being rendered dynamically which is all good.

in Feed.js

const [posts, setPosts] = useState([]);

...

<div id='feed' role="feed">
  {posts.map(
    post => ( <Post setPosts={ setPosts } post={ post } key={ post._id } /> )
  )}
</div>

in Post.js

const handleClick = async () => {
    try {
      await fetch(`/posts/${post._id}`, {
        method: 'delete',
        headers: {
          'Authorization': `Bearer ${token}`
        }
      })
    } catch (err) {
      console.error(err.message);
    }
  };

<div className="post">
  <article data-cy="post" key={ post._id }>{ post.message }</article>
  <button onClick={handleClick}>delete post</button>
</div>

Where Post is a child of Feed.

When the delete button is clicked, the post is deleted from the database as expected, however it is not removed from the page until the browser is refreshed.

How could I have so that when the delete button within the post component is clicked, that the feed component is also re-rendered? I have thought about handing state down, but in order for me to delete a specific post from an array would require me to hand down both posts and setPosts as props, is this bad practice? And what would best practice in React for this scenario, as I feel this is something I will come across a lot.

  • You haven't shown your `handleClick` but it sounds like it isn't updating the `posts` state in the parent. You are passing down`setPosts` to the `Post` components but are you calling it? You could also just pass down a 'dirty' flag or reducer action to trigger new query on the database from the parent. – pilchard Feb 10 '23 at 11:27
  • Thanks for updating the snippet. You'll note that you're never calling `setPosts`. After deleting you'll need to re-query all posts and update the parent state. – pilchard Feb 10 '23 at 11:34
  • @pilchard I've just added the handleClick code. To use `setPosts` i would need to `filter` `posts`, my question is whether it is okay to hand down `posts` and `setPosts` as props – Alex Hoggett Feb 10 '23 at 11:34
  • 2
    Yes, it's fine to hand down state, but better to write a handler or effect in the parent that is triggered by the children. Filtering the state is fine, but at some point you'll want to revalidate against the db. – pilchard Feb 10 '23 at 11:35
  • Thank you, could you kindly provide an example of how this would look? – Alex Hoggett Feb 10 '23 at 11:36
  • Here's a quick [sandbox](https://codesandbox.io/s/basic-revalidation-q07mc9?file=/src/App.js) of a basic revalidation option. But it would be better to encapsulate all the db logic in one place, possibly the Feed component, but probably better a custom hook or context. – pilchard Feb 10 '23 at 15:15
  • Here's a relevant related question: [React useReducer async data fetch](https://stackoverflow.com/questions/53146795/react-usereducer-async-data-fetch) covering a pattern using `useReducer` – pilchard Feb 10 '23 at 15:27

1 Answers1

0

Approach 1: mark the post as deleted

In your Post, you can handle request to the server to delete post.

After that, you can set the isDeleted flag (in Post). If the post is marked as deleted then you just return null. This way you will not render the Post and you didn't touch the state of the parent, which means no other component was rerendered.

Of course, this approach means that if something forces parent to rerender you can lose the internal state of your Post.

Approach 2: filter out deleted posts

As in approach 1 Post is handling deleting request. It also gets onDeleteSuccess callback prop. You can call with deleted post id. Then Feed can filter out deleted posts. This part unfortunately will rerender all posts.

Approach 3: Use React Query

Not direct your case but I think you will get there soon. As you will notice shortly fetching data from the server is not easy. There are many aspects to cover. React Query is a great tool for fetching data. It will cache your fetched data. After deleting the post, you can update the cache. It's similar to approach 2 but with all benefits of React Query.

Sorry if approach 3 is going too far from your original question ;-)

suchy
  • 1