Graphql 数据未合并,Apollo 3与字段策略分页

Graphql 数据未合并,Apollo 3与字段策略分页,graphql,apollo,apollo-client,Graphql,Apollo,Apollo Client,这是我的两份文件。我试图用我自己的数据模拟这个沙箱的结果: 从本质上说,我可以看到数据已被提取和缓存更新,但我的component ResourceSection数据列表没有更新 [更新]根据反馈做出了一些重大更改。从组件中删除了查询,我创建了一个skipLimitPagination函数。查询正常,但我的缓存没有更新数据或将数据放在缓存中 import React from "react"; import { BrowserRouter as Router } from &

这是我的两份文件。我试图用我自己的数据模拟这个沙箱的结果:

从本质上说,我可以看到数据已被提取和缓存更新,但我的component ResourceSection数据列表没有更新

[更新]根据反馈做出了一些重大更改。从组件中删除了查询,我创建了一个skipLimitPagination函数。查询正常,但我的缓存没有更新数据或将数据放在缓存中

import React from "react";
import { BrowserRouter as Router } from "react-router-dom";
import "./App.css";
import { ApolloClient, InMemoryCache, ApolloProvider } from "@apollo/client";
import Home from "./screens";
import { skipLimitPagination } from './utils/utilities'

const client = new ApolloClient({
  uri: `https://graphql.contentful.com/content/v1/spaces/${process.env.REACT_APP_SPACE_ID}/?access_token=${process.env.REACT_APP_CDA_TOKEN}`,
  cache: new InMemoryCache({
   typePolicies: {
     Query: {
       fields: {
         resourceCollection: {items: skipLimitPagination()}
       }
     }
   }
  }),
});

function App() {
  return (
    <ApolloProvider client={client}>
      <Router>
        <Home />
      </Router>
    </ApolloProvider>
  );
}

export default App;

我已经连续三天研究这个问题了。我尝试了更新查询的旧方法,但它没有按预期工作,所以现在我正在尝试最新的apollo技术。请提供帮助:

根查询的类型只是查询,而不是根查询,我认为这就是为什么您对RootQuery.resourceCollection字段的配置没有任何效果

换句话说,请尝试以下方法:

新InMemoryCache{ 类型策略:{ 查询:{//不是RootQuery 字段:{ 资源收集:offsetLimitPagination, }, }, }, }
我还建议您在组件外部创建资源集合查询,这样您就不会在每次呈现组件时都创建新的DocumentNode。

根查询的类型只是查询,而不是根查询,我认为这就是为什么您对RootQuery.resourceCollection字段的配置没有任何效果

换句话说,请尝试以下方法:

新InMemoryCache{ 类型策略:{ 查询:{//不是RootQuery 字段:{ 资源收集:offsetLimitPagination, }, }, }, }
我还建议您在组件外部创建资源集合查询,这样您就不会在每次渲染组件时都创建新的DocumentNode。

我遇到了几乎相同的问题,并找到了解决方案。问题是阿波罗站点上的所有示例都假定响应对象的第一个元素是您的项目数组

这不是Contentful的工作方式,数组总是嵌套在集合中的项中。例如,resourceCollection有一个包含所有资源的属性项。因此,您必须合并这些项,但返回整个resourceCollection,如下所示:

新InMemoryCache{ 类型策略:{ 查询:{ 字段:{ 资源收集:{ keyArgs:false, 合并现有的、传入的{ 如果!传入返回存在 if!existing return incoming//existing第一次将为空 常量{items,…rest}=传入; 让结果=休息; result.items=[…existing.items,…items];//将现有项与传入的项合并 返回结果 } } } } } }
这将返回包含合并项的resourceCollection。

我遇到了几乎相同的问题,并找到了解决方案。问题是阿波罗站点上的所有示例都假定响应对象的第一个元素是您的项目数组

这不是Contentful的工作方式,数组总是嵌套在集合中的项中。例如,resourceCollection有一个包含所有资源的属性项。因此,您必须合并这些项,但返回整个resourceCollection,如下所示:

新InMemoryCache{ 类型策略:{ 查询:{ 字段:{ 资源收集:{ keyArgs:false, 合并现有的、传入的{ 如果!传入返回存在 if!existing return incoming//existing第一次将为空 常量{items,…rest}=传入; 让结果=休息; result.items=[…existing.items,…items];//将现有项与传入的项合并 返回结果 } } } } } }
这将返回包含合并项的resourceCollection。

any;我一定是把这件事搞得太复杂了有人吗;我一定是太复杂了谢谢,为了澄清,我应该将根查询提取到父组件,并将数据作为道具传递下去?这是我的回复,如果这有帮助的话:嗯,也许每次创建一个新的documentNode都会导致我在使用之前的updateQuery语法加载更多内容时出现可笑的屏幕闪烁。我现在在工作,但我一到家就会试试这个!祈求好运,这是我发布我的项目之前的最后一件事。我在午餐休息时有一点时间编辑我的代码。我按照你的指示做了,并更新了上面的代码。现在的问题是,当我将TypePolicys用于resourceCollection时,它返回时未定义。另请注意:我将两个查询移到了一个大查询中。FetchMore仍然调用next 5,但没有更新任何内容……谢谢,为了澄清,我应该将根查询提取到父组件,并将数据作为道具传递下去?这是我的回购协议,如果有帮助的话:嗯,也许是创造一个新的do
每次使用之前使用的updateQuery语法加载更多内容时,cumentNode都会导致我可笑的屏幕闪烁。我现在在工作,但我一到家就会试试这个!祈求好运,这是我发布我的项目之前的最后一件事。我在午餐休息时有一点时间编辑我的代码。我按照你的指示做了,并更新了上面的代码。现在的问题是,当我将TypePolicys用于resourceCollection时,它返回时未定义。另请注意:我将两个查询移到了一个大查询中。FetchMore仍在调用下一个5,但没有更新任何内容……哇,我忘记了这个问题,但感谢您的回复。我会去看看,几个月没碰过那个项目了。哇,我忘了这个问题,但谢谢你的回复。我会查一查的,几个月没碰过那个项目了。
import React, { useState } from "react";
import Navbar from "../components/Navbar";
import MobileNav from "../components/MobileNav";
import HeroSection from "../components/HeroSection";
import FeaturesSection from "../components/FeatureSection";
import Split from "../components/SplitWindow";
import Loading from "../components/Loading";
import { useQuery, gql } from "@apollo/client";
import Resource from "../components/ResourceSection";
import Contact from "../components/ContactSection";
import Footer from "../components/Footer";

const MASS_COLLECTION = gql`
query($skip: Int) {
  resourceCollection(limit: 5, skip: $skip ) {
 items {
   type
   category
   title
   link
   bgColor
   color
 }
},
splitSectionCollection(order: splitId_ASC) {
 items {
   splitId
   lightBg
   left
   lightText
   darkText
   image {
     url
   }
   alt
   heading
   content {
     json
   }
 }
} 

}
`;

const Home = () => {
  const [isOpen, setIsOpen] = useState(false);

  const { loading, error, data, fetchMore } = useQuery(MASS_COLLECTION, {
    variables: {
      skip: 0,
    },
  });

  if (loading) return <Loading />;
  if (error) return <p>Error</p>;

  const toggle = () => {
    setIsOpen(!isOpen);
  };
  return (
    <>
      <MobileNav isOpen={isOpen} toggle={toggle} />
      <Navbar toggle={toggle} />
      <HeroSection />
      <FeaturesSection />
      {data.splitSectionCollection.items.map((item) => {
        return <Split item={item} key={item.splitId} />;
      })}
      <Resource data={data.resourceCollection.items} fetchMore={fetchMore}/>
      <Contact />
      <Footer />
    </>
  );
};

export default Home;

import React, { useState, useCallback } from "react";
import {
  ResourceContainer,
  ResourcesWrapper,
  ResourceRow,
  TextWrapper,
  Column1,
  Heading,
  Content,
  Column2,
  ImgWrap,
  Img,
  Form,
  FormSelect,
  FormOption,
  // LinkContainer,
  // LinkWrapper,
  // LinkIcon,
  // LinkTitle,
  // LoadMore,
  // ButtonWrapper,
} from "./ResourceElements";

const ResourceSection = ({ data, fetchMore }) => {
  console.log(data)

  const handleClick = useCallback(() => {
    fetchMore({
      variables: {
        skip:
          data 
            ? data.length
            : 0,
      },
    });
  }, [fetchMore, data]);

  return (
    <ResourceContainer lightBg={true} id="resource">
      <ResourcesWrapper>
        <ResourceRow left={true}>
          <Column1>
            <TextWrapper>
              <Heading lightText={false}>Resources</Heading>
              <Content darkText={true} className="split_cms">
                Cyber Streets strives in sharing education resources to all.
                Below you can find an exhaustive list of resources covering
                everything from computer programming to enterneurship. "Be
                knowledgeable in your niche, provide some information free of
                charge, and share other trustworthy people's free resources
                whenever possible..." - Heather Hart
              </Content>
            </TextWrapper>
          </Column1>
          <Column2>
            <ImgWrap>
              <Img
                src="/assets/images/Resource.svg"
                alt="Two looking at computer screen svg"
              />
            </ImgWrap>
          </Column2>
        </ResourceRow>
        <Form action="">
          <FormSelect
          // onChange={(e) => {
          //   setCategory(e.target.value);
          //   // setLimit(5);
          // }}
          >
            <FormOption value="">Filter by category</FormOption>
            <FormOption value="MEDIA">Media</FormOption>
            <FormOption value="TEDX">Ted Talks</FormOption>
            <FormOption value="INTERNET SAFETY/AWARENESS">
              Internet safety &amp; awareness
            </FormOption>
            <FormOption value="K-12/COMPUTER SCIENCE">
              k-12 &amp; computer science
            </FormOption>
            <FormOption value="CODING">Programming</FormOption>
            <FormOption value="CYBER/IT OPERATIONS">
              Cyber &and; IT operations
            </FormOption>
            <FormOption value="ROBOTICS">Robotics</FormOption>
            <FormOption value="CLOUD">Cloud</FormOption>
            <FormOption value="SCIENCE">Science</FormOption>
            <FormOption value="PROFESSIONAL DEVELOPMENT">
              Professional Development
            </FormOption>
            <FormOption value="3D PRINTING">3D Printing</FormOption>
            <FormOption value="ART">Art</FormOption>
            <FormOption value="MOOC">Massive Open Online Courses</FormOption>
            <FormOption value="GAMES">Games &amp; Challenges</FormOption>
            <FormOption value="OTHER">Other</FormOption>
          </FormSelect>
        </Form>
        <div className="list">
          {data.map((resource, i) => (
            <div key={resource.title} className="item">
              {resource.title}
            </div>
          ))}
        </div>

        <button className="button" onClick={handleClick}>
          Fetch!
        </button>
      </ResourcesWrapper>
    </ResourceContainer>
  );
};

export default ResourceSection;

ResourceCollection
ARGS
skip: Int = 0
limit: Int = 100
preview: Boolean
locale: String
where: ResourceFilter
order: [ResourceOrder]

Fields
total: Int!
skip: Int!
limit: Int!
items: [Resource]!
export function skipLimitPagination(keyArgs) {
    return {
      keyArgs,
      merge(existing, incoming, { args }) {
        const merged = existing ? existing.slice(0) : [];
        if (args) {
          const { skip = 0 } = args;
          for (let i = 0; i < incoming.length; ++i) {
            merged[skip + i] = incoming[i];
          }
        } else {
  
          merged.push.apply(merged, incoming);
        }
        return merged;
      },
    };
  }