React Apollo - 进行多个查询

IT技术 javascript reactjs apollo react-apollo
2021-05-10 08:07:01

我有一个如下所示的查询文件:

import {gql} from 'react-apollo';

const queries = {
  getApps: gql`
    {
      apps {
        id
        name
      }
    }
  `,
  getSubjects: gql`
    {
      subjects {
        id
        name
      }
    }
  `
};

export default queries;

然后我将此文件导入到我的 React 组件中:

import React, {Component} from 'react'
import queries from './queries'

class Test extends Component {
...
}

export default graphql(queries.getSubjects)(graphql(queries.getApps)(Test));

这只会获取其中一个查询 (getApps) 的数据,而不是两者。如果我一次做一个,它看起来像这样:

export default graphql(queries.getSubjects)(Test);

然后它工作,但我没有我的其他查询。是的,我已经分别测试了它们并且它们有效。我如何获得它以便两个查询都显示在我的 props.data 中?

4个回答

我的首选方法是使用composeapollo 客户端 ( docu ) 的功能。

编辑:如果您有多个查询,您应该命名它们。

所以在你的情况下,它可能是这样的:

import React, {Component} from 'react'
import queries from './queries'
import { graphql, compose } from 'react-apollo';

class Test extends Component {
...

  render() {
    ...
    
    console.log(this.props.subjectsQuery, this.props.appsQuery); // should show both 
    
    ...
  }
}

export default compose(
   graphql(queries.getSubjects, {
      name: "subjectsQuery"
   }),
   graphql(queries.getApps, {
      name: "appsQuery"
   }),
)(Test);

如果您不想独立地重用这些查询中的任何一个,为什么不通过将两个查询组合在一起来发出单个请求,即:

const combinedQueries = gql`
{
  apps {
    id
    name
  }
  subjects {
    id
    name
  }
}
`

然后你可以在你的组件中使用它

import React, {Component} from 'react'
import combinedQueries from './combinedQueries'

class Test extends Component {
   ...
   render() {
     ...
     if(!this.props.combinedQueries.loading) {
       console.log(this.props.combinedQueries.apps);
       console.log(this.props.combinedQueries.subjects);
     }
     ...
   }
}

export default graphql(combinedQueries, {name: 'combinedQueries'})(Test);

恕我直言,Apollo Client React implementation 中描述了最简洁的解决方案之一
基本思想是将您的查询包装到嵌套的 Query 组件中。使用闭包函数作为子组件可以方便地将一个查询的结果委托给另一个查询等等。

 const QueryOne = gql`
  query One {
    one
  }
`;

const QueryTwo = gql`
  query Two {
    two
  }
`;

const NumbersWithData = () => (
  <Query query={QueryOne}>
    {({ loading: loadingOne, data: { one } }) => (
      <Query query={QueryTwo}>
        {({ loading: loadingTwo, data: { two }}) => {
          if (loadingOne || loadingTwo) return <span>loading...</span>
          return <h3>{one} is less than {two}</h3>
        }}
      </Query>
    )}
  </Query>
);

我正在使用react-adopt来做到这一点。这真的很简单,并保持我们的代码干净。

简单的例子:

import { adopt } from 'react-adopt';

...
render() {
  const Composed = adopt({
    first: ({ render }) => <Query query={FIRST_QUERY}>{ render }</Query>,
    second: ({ render }) => <Query query={SECOND_QUERY}>{ render }</Query>
  });

  return (
    <Composed>
      ({ first, second }) => {
        console.log('first', first)
        console.log('second', second)

        // validations (loading, error)

        return (
          <div>Your JSX</div>
        )
      }
    </Composed>
  )
}
...

有很多例子使用

const Composed = adopt({
  first: <Query query={FIRST_QUERY} />,
  second: <Query query={SECOND_QUERY} />
});

小心<Query>组件,它需要一个孩子,否则会出现以下错误:

Warning: Failed prop type: The prop children is marked as required in Query, but its value is undefined.

为了避免之前的警告,我找到了一个可能的解决方案:

first: ({ render }) => <Query query={FIRST_QUERY}>{ render }</Query>

希望对你有帮助!