javascript - Apollo 客户端在 next.js 、 javascript、 graphql、react js 中出现问题

标签 javascript reactjs caching graphql apollo

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

以及它无限调用 api。

如果我移动到另一个页面并再次返回主页,cache.readQuery 就会工作并正确获取帖子的个人资料和 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,
      };
    }

最佳答案

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

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

If your cache doesn't contain all of the data necessary to fulfill a specified query, readQuery throws an error. It never attempts to fetch data from a remote server.

看起来在 readQuery 中添加 try/catch block 是有意义的

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
}

关于javascript - Apollo 客户端在 next.js 、 javascript、 graphql、react js 中出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61666648/

相关文章:

java - 试图将java对象存储在连续内存中

java - Hibernate 一级和二级缓存如何与多个 session 一起工作

javascript - 如何确定所有的angular 2组件都被渲染了?

javascript - jquery fade toggle如何在每个按钮中添加淡入淡出效果

javascript - 任何忽略 undefined variable 的脚本?

javascript - 为什么我的导航器不工作?

javascript - Jquery .each() 仅替换第一个找到的

javascript - ReactJS 如何设置输入文本字段显示当前日期和时间?

reactjs - 类型 'xxx' 缺少类型 'ElementClass' 中的以下属性 : context, setState、forceUpdate、props 以及另外 2 个。 TS2605

c# - Ncache的Web.Cache和ObjectCacheProvider的区别