Home > Enterprise >  React useffect infinite render or stale state
React useffect infinite render or stale state

Time:04-10

I am getting some posts from the server and every time i delete or add a post, i need to refresh the page for it to showcase the changes. This can be solved by adding posts in the dependency array but then an infinite render occurs.

useEffect(() => {
    const getUsersData = async () => {
      const results = await getUsers();
      setUsers(results.data);
      console.log(results.data);
    };

    const getPostData = async () => {
      const results = await getPosts();
      console.log(results.data);
      setPosts(
        results.data.sort((p1, p2) => {
          return new Date(p2.created_at) - new Date(p1.created_at);
        })
      );
    };

    getUsersData();
    getPostData();
  }, [posts]);

{post.user_id === user.result.user_id && (
              <DeleteIcon
                color="secondary"
                onClick={() =>
                  handleDelete(post.post_id, { user_id: user.result.user_id })
                }
              />
            )}

__

export const deletePost = async (postId, userId) => {
  await axios.delete(`${URL}/posts/${postId}`, { data: userId });
};

CodePudding user response:

useEffect(() => {
    const getPostData = async () => {
      ...
      setPosts(
        ...
      );
    };
    getPostData();
}, [posts]);

Oops ! The issue is here, you are setting your post each time you... are setting your posts ! Maybe you should use setpost somewhere else in your code ? :)

If you want to update your posts, you should do it in another useeffect, with whatever dependencies you need to know you need to update your poste. Or do a timed refresh, also in a use effect. You can then call setpost, without having access to post. You don't need post as dependency to update it, on the contrary, that's what's causing a loop here :)

CodePudding user response:

You can't add posts as a dependency to your useEffect ince you are using that effect to call setPosts. This will cause an infinite rerender loop.

Your issue is one of the reasons why many fetch libraries for react have been created in the last few years, like react-query, or RTK query, because what you want to do, is to update your queried data, in response to a mutation on the same data-set on server ( mutations: POST, DELETE, PATCH, PUT ). These libraries let you specify what query data to revalidate once you perform a mutation, in your case, you would tell your getPosts query to be reexecuted and revalidated in cache everytime you perform an addPost or deletePost mutation.

If you want to implement manually both optimistic update and cache revalidation, you need to add some more code, you will have basically these code blocks:

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


const getUsersData = async () => {
    const results = await getUsers();
    setUsers(results.data);
    console.log(results.data);
 };

const getPostsData = async () => {
    const results = await getPosts();
    console.log(results.data);
    setPosts(results.data.sort((p1, p2) => {
          return new Date(p2.created_at) - new Date(p1.created_at);
        })
      );
    };

const handleDelete = async (postId, userId) => {
    await deletePost(postId, userId) // DELETE Call
    const idx = posts.findIndex(p => p.id === postId )
    setPosts(posts => [...posts.slice(0, idx),...posts.slice(idx 1, posts.length)] // Optimistic update of UI
    getPosts()  // Revalidate posts after the delete operation
}

const handleAddPost = async (post, userId) => {
    await addPost(post, userId) // POST Call
    setPosts(posts => [post,...posts] // Optimistic update of UI
    getPosts()  // Revalidate posts after the POST operation
}

// Retrieve data on the first component mount

useEffect(() => {
    getUsersData();
    getPostData();
  }, []);

  • Related