1

I have a page that contains a component that renders a list from the results of a query. When I load the page the first time, the list renders fine. But whenever I go to another page and navigate back, an additional set of the result is appended to the list, creating duplicates in the DOM.

I'm not sure what I'm doing wrong here, but I don't want a new set items to be appended to the list every time I load the page.

apolloClient (https://github.com/vercel/next.js/tree/canary/examples/with-apollo)

let apolloClient;

const createApolloClient = () =>
  new ApolloClient({
    ssrMode: typeof window === "undefined",
    link: new HttpLink({
      uri: DB_URI,
      credentials: "same-origin",
    }),
    cache: new InMemoryCache(),
  });

export function initializeApollo(initialState = null) {
  const _apolloClient = apolloClient ?? createApolloClient();

  if (initialState) {
    const existingCache = _apolloClient.extract();
    const data = merge(initialState, existingCache);

    _apolloClient.cache.restore(data);
  }

  if (typeof window === "undefined") return _apolloClient;
  if (!apolloClient) apolloClient = _apolloClient;
  return _apolloClient;
}

export function addApolloState(client, pageProps) {
  if (pageProps?.props) {
    pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract();
  }
  return pageProps;
}

export function useApollo(pageProps) {
  const state = pageProps[APOLLO_STATE_PROP_NAME];
  return useMemo(() => initializeApollo(state), [state]);
}

On my page I use getStaticProps as follows

export async function getStaticProps() {
  const apolloClient = initializeApollo();

  await apolloClient.query({
    query: GET_THINGS,
  });

  return addApolloState(apolloClient, {
    props: {},
    revalidate: 1,
  });
}

My list component looks as follows:

const ItemsList: React.FunctionComponent<Props> = (props) => {
  const { loading, error, data } = useQuery(GET_THINGS, {});

  const { items} = data;
  const { filters } = props;

  const [filteredItems, setFilteredItems] = useState(items);

  useEffect(() => {
    setFilteredItems(filterItems(items, filters));
  }, [filters, items]);

  const renderItems = (filteredItems: Array<Item>) =>
    filteredItems.map((item) => (
      <li key={item.id}>
        <Link href={`/items/${item.id}`}>{item.name}</Link>
      </li>
    ));

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

  return (
    <div>
      {filteredItems?.length > 0 ? (
        <ul>{renderItems(filteredItems)}</ul>
      ) : (
        <span>No items matched the criteria</span>
      )}
    </div>
  );
};

export default ItemsList;
Brownsted
  • 11
  • 1
  • Did you manage to find a fix? – Norbert Dec 07 '20 at 18:37
  • Nope, the project was in very early stages, so I started over and suddenly it worked fine. Not sure what I did different except by following documentations more closely :) – Brownsted Dec 08 '20 at 19:28

0 Answers0