Preventing redundant refetch and repaint for child elements in a list

I am creating a demo of a social media feed that contains a list of posts, each post is clickable and takes the user to a detailed page for the post.

function FeedContainer (props) {
  const { loading, error, data, fetchMore } = useQuery(props.fetchMore, {
    variables: { ...props.variables },
  });

  if (loading) {
    return <div />;
  }

  if (error) {
    return <div>{`Error! ${error.message}`}</div>;
  }

  return (
      {data.edges.map((item, index) => {
        return (
          <Post
            {...item}
            key={item.transaction}
            subFeedContext={props.subFeedContext}
          />
        )
      }
   )

Some of these posts contain a link to another post, in which case I am using an apollo hook useQuery to fetch that child post’s data and returning that in the list instead.

export function PostComponent(props) {
  const fetchPost = gql`
    ${SIMPLE_POST_INFO}

    query QueryPostByTx($transaction: String!) {
      allPosts(first: 1, filter: { transaction: { equalTo: $transaction } }) {
        edges {
          node {
            ...SimplePostInfo
          }
        }
      }
    }
  `;

  const { loading, error, data } = useQuery(fetchPost, {
    variables: {
      transaction: props.transaction,
    },
    fetchPolicy: 'cache-and-network'
  });

  if (loading) return <div />;
  if (error || data == null) return <div>error</div>;

  return (
    <Post
      {...data}
      key={props.transaction}
    />
  );
}

The problem I am experiencing is when a user clicks on a post to go to the detailed post page, and then clicks back to resume scrolling down the list from where they left off. All of the posts that contain a link and require the inner-child fetch component will refetch and repaint, causing the list to jump around. The rerender issue does not happen for posts without this inner-child fetch and render. If I remove the inner fetch, then the scrollbar retains the position of the list when the user clicks back.

I have tried useMemo, adding keys to the component elements, setting apollo fetch policies, removing all instances of anonymous functions, and still this inner child query refetches each time to retrieve the same data. Is there a way to retain the state when using a router with apollo, such that the list wont jump around on a history pop? Would appreciate any help, resources to help address this problem.

here is a gif of this repaint example

1 Like