首页 > 解决方案 > Apollo GraphQL 将重复项附加到组件状态

问题描述

我有一个页面,其中包含一个从查询结果呈现列表的组件。当我第一次加载页面时,列表呈现良好。但是,每当我转到另一个页面并返回时,就会将一组额外的结果附加到列表中,从而在 DOM 中创建重复项。

我不确定我在这里做错了什么,但我不希望每次加载页面时都将新的设置项附加到列表中。

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]);
}

在我的页面上,我使用 getStaticProps 如下

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

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

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

我的列表组件如下所示:

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;

标签: javascriptreactjsnext.jsreact-apolloapollo-client

解决方案


推荐阅读