如何将HOC转换为对阿波罗的组件语法作出反应?

时间:2019-01-22 20:01:04

标签: reactjs apollo next.js

有人可以帮助我理解如何抽象化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

1 个答案:

答案 0 :(得分:1)

要详细说明我的评论,并使用<Query>语法:

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;