【问题标题】:Apollo client issues in next.js , javascript, graphql, react jsnext.js、javascript、graphql、react js 中的 Apollo 客户端问题
【发布时间】:2020-08-23 06:31:53
【问题描述】:

如果我首先访问主页或刷新主页,我无法在解析器中获取配置文件,因为 cache.readQuery 不起作用。

以及它无限调用api。

如果我移动到另一个页面并再次返回主页,cache.readQuery 将正常工作并正确获取 post 的 profile 和 voteStatus。

以前有人遇到过这个问题吗? home.tsx 是我项目的主页。

此外,useQuery(@apollo/react-hooks) 在每个页面上获取旧数据。

如果你有经验,请帮助我。

  • home.tsx
    ...
    const GET_POSTS = graphql`
      query posts($accountname: String!, $page: Int, $pathBuilder: any, $postsStatus: String) {
        posts(accountname: $accountname, page: $page, postsStatus: $postsStatus)
          @rest(type: "Post", pathBuilder: $pathBuilder) {
          post_id
          author
          voteStatus(accountname: $accountname) @client
          created_at
        }
      }
    `;
    interface Props {
      author: string;
    }
    const Home: NextPage<Props> = ({ author }) => {
      const { data, fetchMore, loading } = useQuery(GET_POSTS, {
        variables: {
          accountname: author,
          page: 1,
          postsStatus: 'home',
          pathBuilder: () => `posts/?Page=1&Limit=5&domainId=1`,
        },
      });
      const loadMorePosts = () => {
        fetchMore({
          variables: {
            page: page + 1,
            pathBuilder: () => `posts/?Page=${page + 1}&Limit=5&domainId=1`,
          },
          updateQuery: (previousResult, { fetchMoreResult }) => {
            if (!fetchMoreResult) {
              return previousResult;
            }
            setPage(page + 1);
            return Object.assign({}, previousResult, {
              posts: [...previousResult.posts, ...fetchMoreResult.posts],
            });
          },
        });
      };
      return (
        <div></div>
      );
    };
    interface Context extends NextPageContext {
      apolloClient: ApolloClient<NormalizedCacheObject>;
    }
    Home.getInitialProps = async (ctx: Context) => {
      const cookies = nextCookie(ctx);
      const author = cookies[encodeURIComponent(KARMA_AUTHOR)];
      ctx.apolloClient.writeData({
        data: {
          accountName: author,
        },
      });
      return {
        layoutConfig: { layout: labels.DEFAULT },
        meta: {
          title: 'Home',
        },
        author,
      };
    };
    export default withAuthSync(withApollo({ ssr: true })(Home));
  • withApollo.tsx
    import { ApolloClient } from 'apollo-client';
    import { withClientState } from 'apollo-link-state';
    import serverFetch from 'node-fetch';
    import graphql from 'graphql-tag';
    const GET_PROFILE = graphql`
      query Profile($accountname: String!, $domainID: number) {
        profile(accountname: $accountname, domainID: $domainID)
          @rest(type: "Profile", path: "profile/{args.accountname}?domainID={args.domainID}") {
          author
          followers_count
          following_count
        }
      }
    `;
    const cache = new InMemoryCache({
      cacheRedirects: {
        Query: {
          post: (_, { post_id }, { getCacheKey }) => getCacheKey({ __typename: 'Post', post_id }),
        },
      },
      dataIdFromObject: object => {
        switch (object.__typename) {
          case 'Post':
            return getUniquePostId(object.post_id);
          case 'Comment':
            return getUniqueCommentId(object.cmmt_id);
          case 'Profile':
            return object.author;
          default:
            defaultDataIdFromObject(object);
        }
      },
    });
    const resolvers = {
      Post: {
        voteStatus: async ({ post_id }, args, { cache }, info) => {
          const { profile } = cache.readQuery({
            query: GET_PROFILE,
            variables: {
              accountname: args.accountname,
              domainID: 1,
            },
          });
          console.log(profile); // can't make console log because profile is not coming from readQuery
          if (profile) {
            return 1;
          } else {
            return 0;
          }
        },
      },
    };
    const stateLink = withClientState({
      cache,
      resolvers,
    });
    const restLink = new RestLink({
      uri: `${SERVER_URL}/`,
      serverFetch,
    });
    const createApolloClient = (initialState: NormalizedCacheObject, ctx: NextPageContext) => {
      return new ApolloClient({
        ssrMode: true,
        link: ApolloLink.from([stateLink, restLink]),
        cache,
      });
    }
    ...
    export const withApollo = ({ ssr = false } = {}) => (PageComponent: NextPage) => {
      const client = createApolloClient(initialState, ctx);
      ...
      return {
        ...pageProps,
        apolloState: apolloClient.cache.extract(),
        apolloClient: ctx.apolloClient,
      };
    }

【问题讨论】:

    标签: javascript reactjs caching graphql apollo


    【解决方案1】:

    cache.readQuery 无法读取不存在的数据 - 必须先查询数据

    您可能正在切换的页面之一查询此数据(配置文件),使其在您返回 &lt;Home/&gt; 时可用。

    解决方案 - 在查询帖子之前先查询个人资料:

    const Home: NextPage<Props> = ({ author }) => {
      const { data: dataProfile, error: errorProfile, loading: loadingProfile } = useQuery(GET_PROFILE);
      const { data, fetchMore, loading } = useQuery(GET_POSTS, {
        skip: !dataProfile,
        variables: {
          accountname: author,
          page: 1,
          postsStatus: 'home',
          pathBuilder: () => `posts/?Page=1&Limit=5&domainId=1`,
        },
      });
    

    skip 选项用于块查询,直到满足条件。

    在收到个人资料数据(并将其写入缓存)后获取帖子。这样本地解析器 (voteStatus) 可以使用 cache.readQuery() 访问所需的数据。

    【讨论】:

      【解决方案2】:

      我没有使用此设置,只是假设您的应用可能正在清除缓存,因此当最初尝试在主页上获取该查询时它会失败。

      我可能又错了,但根据这些文档:https://www.apollographql.com/docs/react/caching/cache-interaction/#readquery

      如果您的缓存不包含完成某个任务所需的所有数据 指定查询,readQuery 抛出错误。它从不尝试获取 来自远程服务器的数据。

      看起来给你的readQuery添加一个try/catch块是有意义的

      let profile;
      try {
        result = cache.readQuery({
          query: GET_PROFILE,
          variables: {
            accountname: args.accountname,
            domainID: 1,
          },
        });
        profile = result.profile;
      } catch(err) {
        console.error(err);
        // do something like printing an error in console, or nothing
      }
      

      【讨论】:

      • 这总是让我陷入困境,所以我无法获取个人资料。
      • 感谢您的回答,但这不是解决此问题的方法
      猜你喜欢
      • 2022-10-25
      • 2021-10-12
      • 2023-04-09
      • 2022-12-12
      • 2023-03-19
      • 2021-04-21
      • 2019-06-22
      • 2018-04-12
      • 1970-01-01
      相关资源
      最近更新 更多