如何在组件外调用 GraphQL

Kim*_*sen 11 apollo reactjs graphql

我已经使用 Query 组件制作了一堆调用 GraphQL 的 React 组件,并且一切正常。

在一个组件中,我需要从数据库中获得一些初始数据,但没有任何可视化表示。

我曾尝试使用查询组件,但它似乎仅在渲染周期中触发。我尝试将其打包成一个函数,并在需要数据的组件中调用该函数。但是代码/查询没有执行,因为没有要显示的组件。

如何在没有组件的情况下从数据库中获取这些数据?

我找不到有关如何解决此问题的任何文档。但我不能是唯一一个这样做的人。

ApolloConsumer 或 ApolloProvider 是我问题的答案吗?

我正在处理会议和会议。会议持续几天,每天都有许多会议。

我想要实现的是每天渲染一个包含 X 个标签的页面。每个选项卡代表一天,并显示当天的会话数。

我的会话页面:

    import React from 'react';
import FullWidthTabs from '../components/Sessions';
import SessionTab from '../components/SessionTab';
import BwAppBar2 from '../components/BwAppBar2';
import ConferenceDays from '../components/ConferenceDays';


class SessionsPage extends React.Component {

    static async getInitialProps() {
        console.log("GetInitProps SessionsPage");
    }

    render() {
        let a = ConferenceDays();
        return (

                <div>
                    <BwAppBar2 />
                    {a}
                     <FullWidthTabs days={['2018-06-11', '2018-06-12', '2018-06-13']} day1={ < SessionTab conferenceId = "57" day = '2018-06-11' / > } 
                                   day2={ < SessionTab conferenceId = "57" day = '2018-06-12' / > } day3={ < SessionTab conferenceId = "57" day = '2018-06-13' / > }>
                    </FullWidthTabs>
                </div>
                );
        }
}
export default (SessionsPage);
Run Code Online (Sandbox Code Playgroud)

此处的日期已硬编码在页面中,仅供测试。

但是为了知道会议跨越多少天,我必须找到会议并决定开始和结束日期并生成其间的所有日期:

import React, { Component } from 'react'
import { graphql } from 'react-apollo'
import { Query } from 'react-apollo'
import gql from 'graphql-tag'
import Link from '@material-ui/core/Link';
import { useQuery } from "react-apollo-hooks";

import conferencesQuery from '../queries/conferences'
import { Table, Head, Cell } from './Table'
import ConferenceCard from './ConferenceCard';
import Grid from '@material-ui/core/Grid';
import Paper from '@material-ui/core/Paper';
import moment from 'moment';


const CONFERENCE_QUERY = gql`
 query conference($conferenceId : ID!){
      conference(id: $conferenceId){
          title
          start_date
          end_date
     }    
}
`
let index = 0;
let loopDate = 0;
let dates = [];
let conferenceId = 57;

const ConferenceDays = () => (
<Query query={CONFERENCE_QUERY} variables={{conferenceId}}>
    {({ loading, error, data }) => {
                        if (loading)
                            return <div>Fetching</div>
                        if (error)
                            return <div>Error</div>
                        const startDate = moment(data.conference.start_date, 'x');
                        const endDate = moment(data.conference.end_date, 'x');

                        for (loopDate = parseInt(data.conference.start_date);
                                loopDate < parseInt(data.conference.end_date);
                                loopDate += 86400000) {

                            let aDate = moment(loopDate, 'x');
                            dates.push(aDate.format('YYYY-MM-DD').toString());
                        }
                        console.log(dates);
                        return(dates);
                    }}
</Query>);

export default ConferenceDays
Run Code Online (Sandbox Code Playgroud)

但是这种方法不正确吗?

在层次结构中提升 ConferenceDates 组件是否更正确?

sli*_*den 6

您可以将 的创建分离ApolloClient到一个单独的文件中,并使用 init 函数来访问 React 组件之外的客户端。

import React from 'react';
import {
  ApolloClient,
  HttpLink,
  InMemoryCache,
} from "@apollo/client";

let apolloClient;

const httpLink = new HttpLink({
  uri: "http://localhost:4000/graphql",
  credentials: "same-origin",
});

function createApolloClient() {
  return new ApolloClient({
    link: httpLink,
    cache: new InMemoryCache(),
  });
}

export function initializeApollo() {
  const _apolloClient = apolloClient ?? createApolloClient();
  if (!apolloClient) apolloClient = _apolloClient;

  return _apolloClient;
}

export function useApollo() {
  const store = useMemo(() => initializeApollo(initialState), [initialState]);
  return store;
}
Run Code Online (Sandbox Code Playgroud)

然后你会像这样使用这个外部组件:

const client = initializeApollo()
const res = await client.query({
  query: MY_QUERY,
  variables: {},
})
Run Code Online (Sandbox Code Playgroud)

我自己没有尝试过,但我认为这是关于如何进行此操作以及如何访问ApolloClient.


Si *_*Thu 4

如果您使用函数式组件,则可以在函数中使用 useApolloClient 钩子,就好像它不是钩子一样。

import { useApolloClient, gql } from "@apollo/client";

 MY_QUERY = gql'
   query OUR_QUERY {
     books{
        edges{
           node{
             id
             title
             author
            }
         }
      }
   }
'

const myFunctionalComponent = () => {   // outside function component

    const client = useApolloClient();

    const aNormalFunction = () => {   // please note that this is not a component  
       client.query({
          query: MY_QUERY,
          fetchPolicy: "cache-first"   // select appropriate fetchPolicy
       }).then((data) => {
          console.log(data)   //do whatever you like with the data
       }).catch((err) => {
          console.log(err)
       })
    };

    // just call it as a function whenever you want
    aNormalFunction()    
    
    // you can even call it conditionally which is not possible with useQuery hook
    if (true) {
        aNormalFunction()
    }

    return (
        <p>Hello Hook!</>
    );
};

export default myFunctionalComponent;
Run Code Online (Sandbox Code Playgroud)