【问题标题】:How to convert HOC to react component syntax for apollo?如何将 HOC 转换为 apollo 的组件语法?
【发布时间】:2019-06-16 08:34:30
【问题描述】:

谁能帮我理解如何抽象出 apollo graphQL 逻辑,以便在使用带有 HOC 的 apollo 与使用更现代的 <Query>({data, loading})=>(<MyComponent data={data} loading={loading}/>)</Query> 语法之间进行转换?或者,如果我不能这样做,您如何在不是整个页面本身的子组件中使用 HOC?我正在使用 next-apollo-appsync 来处理我所有的 graphQL 问题:

import { withAppSyncData } from "next-apollo-appsync";
import AppSyncConfig from "./aws-exports";

const config = {
  url: AppSyncConfig.aws_appsync_graphqlEndpoint,
  region: AppSyncConfig.aws_appsync_region,
  auth: {
    type: AppSyncConfig.aws_appsync_authenticationType,
    apiKey: AppSyncConfig.aws_appsync_apiKey
  }
};

export default withAppSyncData(config);

使用 appsync 设置创建 withData 函数后,我使用 withData 函数创建 TodosWithData 函数。

import withData from "../../lib/withData";
import gql from "graphql-tag";
import { graphql } from "react-apollo";

const query = gql`
  query listTodos {
    listTodos {
      items {
        id
        name
        completed
      }
    }
  }
`;

const TodosWithData = MyComponent =>
  withData(
    graphql(query, {
      options: {
        fetchPolicy: "cache-and-network"
      },
      props: props => ({ todos: props.data.listTodos ? props.data.listTodos.items : [] })
    })(MyComponent)
  );

export default TodosWithData;

这个函数将一个 react 组件作为输入,并返回包裹在组件周围的 apollo,我们将可以访问 this.props.data 下的数据,就像我们期望的那样。奇怪的是,我可以让下面的这个愚蠢的组件工作,但前提是它在页面级别 - 如果我将它移动到我从页面加载的组件,它就不起作用。

import React from "react";
import TodosQuery from "../graphql/components/todos";

class Todos extends React.Component {
  render() {
    console.log(this.props); //We have access to the apollo payload
    return (
      <div>
        <p>Static Text</p>
      </div>
    );
  }
}

//This is what injects apollo payload into the Todos dumb-component.
export default TodosQuery(Todos); 

这里有一个working repo 供参考。我得到的实际错误是Cannot read property 'apollo' of undefined

【问题讨论】:

  • 我相信withData HOC必须应用于页面级别(src/index.js中的App组件)因为它调用getInitialProps,它只能在页面中使用,不能在子页面中使用组件。
  • 使用withData 允许我将待办事项移动到不同的文件中,这是一个很好的开始!只要您在页面上保留withData,您是否可以使用&lt;Query&gt; 语法?

标签: reactjs apollo next.js


【解决方案1】:

详细说明我的评论,并使用&lt;Query&gt; 语法:

src/index.js:

import React from "react";
import withData from "../lib/withData";
import TodosWithData from "../graphql/components/todos";

class App extends React.Component {
  render() {
    console.log("props: ", this.props);
    return (
      <div>
        <p>Hello World</p>
        <TodosWithData />
      </div>
    );
  }
}

export default withData(App);

src/graphql/components/todos.js:

import React from "react";
import { Query } from "react-apollo";
import gql from "graphql-tag";

const query = gql`
  query listTodos {
    listTodos {
      items {
        id
        name
        completed
      }
    }
  }
`;

const TodosWithData = () => (
  <Query query={query} fetchPolicy="cache-and-network">
    {({ loading, error, data: { listTodos } }) => {
      if (error) return <div>Error loading todos</div>
      if (loading) return <div>Loading...</div>
      return (
        <div>
          <ul>
            {listTodos.items.map(todo => (
               <li key={todo.id}>{`${todo.name}${todo.completed ? " - DONE" : ""}`}</li>
            ))}
          </ul>
        </div>
      )
    }}
  </Query>
);

export default TodosWithData;

【讨论】:

  • 或者,您可以从外部文件导入查询,或将其作为道具传递,不必在组件文件中定义。
  • 另外,不确定您的查询是返回多个项目的单个列表,还是多个项目的多个列表。如果是第二种选择,那么您还需要一个外部 .map 来在迭代项目之前迭代列表;)
  • 我试过你的例子,这绝对是有道理的,但我得到了这个错误:Error: GraphQL error: Validation error of type FieldUndefined: Field 'listTodos' in type 'Query' is undefined @ 'listTodos'我做了一个新的分支,映射部分被注释掉了。我可以让它以原始方式工作,但不能使用组件语法。也许是next-apollo-appsync 问题?这是next-apollogithub.com/CaptainChemist/next-appsync-example/tree/newsyntax的一个分支
  • @Coherent 这看起来像一个普通的 GraphQL 错误。您是否使用 GraphiQL 或 GraphQL Playground 等工具验证了您的查询?你能告诉我你的 GraphQL 架构吗?没有这些信息很难给你一个准确的答案。谢谢。
  • 你完全正确,这是我的用户错误,因为没有正确设置 appsync。上面的那个 repo 已经更新为使用组件语法工作。非常感谢 Jaxx!
猜你喜欢
  • 2019-10-05
  • 2020-10-04
  • 2017-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-22
  • 2019-01-04
相关资源
最近更新 更多