【问题标题】:How to use Apollo GraphQL subscriptions in the client-side NextJS?如何在客户端 NextJS 中使用 Apollo GraphQL 订阅?
【发布时间】:2020-08-27 18:54:48
【问题描述】:

我是 NextJS 的新手。我有一个页面需要显示从 Hasura GraphQL 后端提取的实时数据。

在其他非 NextJS 应用程序中,我将 GraphQL 订阅与 Apollo 客户端库一起使用。在引擎盖下,这使用了 websockets。

当它使用订阅时,我可以让 GraphQL 在 NextJS 中工作。我很确定这是在服务器端运行的:

import React from "react";
import { AppProps } from "next/app";
import withApollo from 'next-with-apollo';
import { ApolloProvider } from '@apollo/react-hooks';
import ApolloClient, { InMemoryCache } from 'apollo-boost';
import { getToken } from "../util/auth";

interface Props extends AppProps {
    apollo: any
}

const App: React.FC<Props> = ({ Component, pageProps, apollo }) => (
    <ApolloProvider client={apollo}>
        <Component {...pageProps}/>
    </ApolloProvider>
);

export default withApollo(({ initialState }) => new ApolloClient({
    uri: "https://my_hasura_instance.com/v1/graphql",
    cache: new InMemoryCache().restore(initialState || {}),
    request: (operation: any) => {
        const token = getToken();
        operation.setContext({
            headers: {
                authorization: token ? `Bearer ${token}` : ''
            }
        });
    }
}))(App);

我是这样使用的:

import { useQuery } from '@apollo/react-hooks';
import { gql } from 'apollo-boost';

const myQuery = gql`
    query {
        ...
    }
`;

const MyComponent: React.FC = () => {
    const { data } = useQuery(myQuery);
    return <p>{JSON.stringify(data)}</p>
}

但是,我想这样做:

import { useSubscription } from '@apollo/react-hooks';
import { gql } from 'apollo-boost';


const myQuery = gql`
    subscription {
        ...
    }
`;

const MyComponent: React.FC = () => {
    const { data } = useSubscription(myQuery);
    return <p>{JSON.stringify(data)}</p>
}

我的尝试

我尝试在 ApolloClient 中拆分 HttpLink 和 WebsocketLink 元素,如下所示:

import React from "react";
import { AppProps } from "next/app";

import { ApolloProvider } from '@apollo/react-hooks';
import withApollo from 'next-with-apollo';
import { InMemoryCache } from "apollo-cache-inmemory";
import ApolloClient from "apollo-client";
import { split } from 'apollo-link';
import { HttpLink } from 'apollo-link-http';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';

import { getToken } from "../util/auth";

interface Props extends AppProps {
    apollo: any
}

const App: React.FC<Props> = ({ Component, pageProps, apollo }) => (
    <ApolloProvider client={apollo}>
        <Component {...pageProps}/>
    </ApolloProvider>
);

const wsLink = new WebSocketLink({
    uri: "wss://my_hasura_instance.com/v1/graphql",
    options: {
        reconnect: true,
        timeout: 10000,
        connectionParams: () => ({
            headers: {
                authorization: getToken() ? `Bearer ${getToken()}` : ""
            }
        })
    },
});

const httpLink = new HttpLink({
    uri: "https://hasura-g3uc.onrender.com/v1/graphql",
});

const link = process.browser ? split(
    ({ query }) => {
        const definition = getMainDefinition(query);
        return (
            definition.kind === 'OperationDefinition' &&
            definition.operation === 'subscription'
        );
    },
    wsLink,
    httpLink
) : httpLink;

export default withApollo(({ initialState }) => new ApolloClient({
    link: link,
    cache: new InMemoryCache().restore(initialState || {}),
}))(App);

但是当我加载页面时,我得到一个Internal Server Error,并且在终端中出现这个错误:

Error: Unable to find native implementation, or alternative implementation for WebSocket!

在我看来,ApolloClient 是在服务器端生成的,那里没有 WebSocket 实现。如何在客户端实现这一点?

【问题讨论】:

  • 我也有同样的问题...

标签: reactjs typescript next.js apollo apollo-client


【解决方案1】:

【讨论】:

    【解决方案2】:

    这个答案似乎更实际

    https://github.com/apollographql/subscriptions-transport-ws/issues/333#issuecomment-775578327

    您应该通过npm i ws 安装ws 并将webSocketImpl: ws 添加到WebSocketLink 参数。

    import ws from 'ws';
    
    const wsLink = new WebSocketLink({
        uri: endpoints.ws,
        options: {
            reconnect: true,
            connectionParams: () => ({
                ...getToken() && {Authorization: getToken()}
            })
        },
        webSocketImpl: ws
    });
    

    【讨论】:

      猜你喜欢
      • 2022-12-12
      • 2019-01-14
      • 2017-12-20
      • 2019-01-18
      • 2019-05-18
      • 2018-12-10
      • 2018-12-30
      • 2017-12-25
      • 2017-12-01
      相关资源
      最近更新 更多