skip to Main Content

I am working on a project which have multiple routes like /profile /admin /home
I am fetching posts from backend using Redux Toolkit query in profile page and getting posts successfully but when I go to another page and come back to profile and dispatch again the posts in the states

import { Link, useLocation } from "react-router-dom";
import Tweets from "../components/Tweets";
import { FaEdit } from "react-icons/fa";
import { useGetUserDetailsQuery } from "../slices/userApiSlice";
import ProfileRightBar from "../components/ProfileRightBar";
import { toast } from "react-toastify";
import Spinner from "../components/Spinner";
import { useEffect, useState, useRef } from "react";
import { useGetUserPostsQuery } from "../slices/postApiSlice";
import { useDispatch, useSelector } from "react-redux";
import { updateUserPosts } from "../slices/postSlice";

const ProfileScreen = () => {
  const [page, setPage] = useState(1);
  const [hasMore, setHasMore] = useState(true);

  const lastPostRef = useRef();
  const location = useLocation();
  const dispatch = useDispatch();
  const username = location.pathname.split("/")[2];


  const { data: posts, isFetching } = useGetUserPostsQuery();

  const { userPosts } = useSelector((state) => state.posts);

  useEffect(() => {
    toast.error(error?.data?.message);
  }, [error]);

  useEffect(() => {
    if (posts) {
      if (posts.length === 0) {
        setHasMore(false);
      } else {
        dispatch(updateUserPosts(posts));
      }
    }
  }, [posts]);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting && !isFetching && hasMore) {
          // Fetch more posts when last post is intersecting
          setPage((prevPage) => prevPage + 1);
        }
      },
      { threshold: 1 }
    );

    if (lastPostRef.current) {
      observer.observe(lastPostRef.current);
    }

    // Cleanup the observer
    return () => observer.disconnect();
  }, [isFetching]);

  if (isLoading) {
    return <Spinner />;
  } else if (error) {
    return null;
  } else {
    return (
      <div className="w-full h-screen overflow-scroll">
        <div className="flex">
          <div className="border-r border-lightgray flex-[0.7]  h-screen overflow-auto">
            <Tweets posts={userPosts} />
            <div ref={lastPostRef}></div>
          </div>
        </div>
      </div>
    );
  }
};

export default ProfileScreen;

the main problem is when i come back to profile page it dispatch again the same posts in my array

the updateUserPost slice is here

const initialState = {
  posts: [],
  userPosts: [],
};

const postSlice = createSlice({
  name: "posts",
  initialState,
  reducers: {
    updateUserPosts: (state, action) => {
      state.userPosts.push(...action.payload);
    },
  },
});

2

Answers


  1. That is how effects run. See what happens when you come back to the page is that the component is mounted again and the server call is made again. After the server call dispatch(updateUserPosts(posts)) is run again.

    I guess in updateUserPosts, you are appending the posts passed. You should ideally only add the posts if they already do not exist. You can use filter() or Set to get unique elements.

    Login or Signup to reply.
  2. Redux Toolkit Query (RTK Query) takes care of storing fetched data for you, so you may not have to create extra storage for posts unless you have a special reason for it.

    You are getting posts with useGetUserPostsQuery() and then saving them again in your Redux store with updateUserPosts(posts) even though it’s not necessary. This may not be needed because RTK Query’s caching system should take care of loading and saving your posts.

    Every time you go to your profile, the useGetUserPostsQuery() could be getting data again because of how it’s set up or because it’s not being cached properly.

    You don’t have to keep the posts you get in your Redux unless you’re changing or combining the data in a way that RTK Query can’t do.

    You can use filter() or Set to get distinct posts.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search