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;