首页 > 解决方案 > Apollo GraphQL 数据解构不起作用

问题描述

我正在挖掘graphql,所以我遵循了一个教程,并且我坚持了这一部分。

主页.js

function Home() {
  const {
    loading,
    data: { getPosts: posts }   // <===## Here ##
  } = useQuery(FETCH_POSTS_QUERY);

  return (
      <div>
        {loading ? (
          <h1>Loading posts..</h1>
        ) : (
          posts &&
          posts.map((post) => (
            <p>
              {post.content}
            </p>
          ))
        )}
      </div>
  );
}

const FETCH_POSTS_QUERY = gql`
  {
    getPosts {
      id
      content
    }
  }
`;


export default Home;

解析器

  Query: {
    async getPosts() {
      try {
        const posts = await Post.find().sort({ createdAt: -1 });
        return posts;
      } catch (err) {
        throw new Error(err);
      }
    }
  },

完整代码:https ://github.com/hidjou/classsed-graphql-mern-apollo/tree/react10

在上面的示例中运行良好,它使用它data: { getPosts: posts }来解构返回的数据。但是在我的代码中,我遵循了它,但是出现了错误

TypeError:无法读取未定义的属性“getPosts”

相反,如果我像下面这样编码,

function Home() {
  const {
    loading,
    data // <===## Here ##
  } = useQuery(FETCH_POSTS_QUERY);

  if(loading) return <h1>Loading...</h1>

  const { getPosts: posts } = data // <===## Here ##

  return (
      <div>
        {loading ? (
          <h1>Loading posts..</h1>
        ) : (
          posts &&
          posts.map((post) => (
            <p>
              {post.content}
            </p>
          ))
        )}
      </div>
  );
}

它运作良好。似乎我的代码data在加载之前尝试引用。但我不知道为什么会这样。代码几乎相同。不同的事情是1. my code is on nextjs2. my code is on apollo-server-express。其他事情几乎相同,我的解析器使用async/await,并将返回posts。我错过了什么吗?

我的解析器如下所示。

 Query: {
    async getPosts(_, { pageNum, searchQuery }) {
      try {
        const perPage = 5
        const posts =
          await Post
            .find(searchQuery ? { $or: search } : {})
            .sort('-_id')
            .limit(perPage)
            .skip((pageNum - 1) * perPage)
        return posts
      } catch (err) {
        throw new Error(err)
      }
    },

标签: graphqlreact-apolloapollo-client

解决方案


您的教程可能已过时。在旧版本的 Apollo Client 中,data最初设置为空对象。这样,如果您的代码访问了它上面的某些属性,它就不会崩溃。虽然这很方便,但也不是特别准确(没有数据,为什么我们要提供一个对象?)。现在,data在您的操作完成之前只是未定义。这就是后一个代码起作用的原因——在 afterloading为 false 之前,您不会访问数据的任何属性,这意味着查询已完成并且data不再未定义。

如果你想data在你的钩子被声明时解构,你可以使用这样的默认值:

const {
  loading,
  data: { getPosts: posts } = {}
} = useQuery(FETCH_POSTS_QUERY)

如果您愿意,您甚至可以posts为它分配一个默认值。

请记住另外两件事:第一,如果发生网络错误,即使更改为,也data保持未定义,因此请确保您的代码考虑到这种情况。第二,根据您的架构,如果您的响应中有,您的整个对象可能最终为空。在这种情况下,您仍然会遇到解构问题,因为默认值仅适用于 undefined,而不适用于 null。loadingtrueerrorsdata


推荐阅读