在 Hasura、Apollo和React中实现实时更新的订阅功能

如果需要的话,我会重新写下來的。

实现代码

需要将通信从HTTP切换到WebSocket,因此需要安装插件。

yarn add subscriptions-transport-ws

使用WebSocketLink将ApolloClient的link更改为ws。

原本的URI是在URI中通过HTTP指定的,为http://localhost:8080/v1/graphql。
由于想要进行双向通信,所以将其更改为ws://localhost:8080/v1/graphql。

在这个时候,Hasura方面没有任何特定的行动需要。

import {
  ApolloClient,
  InMemoryCache,
  gql
} from "@apollo/client";
import { WebSocketLink } from "@apollo/client/link/ws";
import { useSubscription } from '@apollo/react-hooks'
import ArticleCards from '../components/ArticleCards'

const client = new ApolloClient({
  // uriをlinkに変更(http通信からws通信にする)
  link: new WebSocketLink({
    uri: 'ws://localhost:8080/v1/graphql',
    options: {
      reconnect: true,
       connectionParams: {
          headers: {
            // 認証系はここに書く
          }
       }
    }
  }),
  cache: new InMemoryCache(),
 });

export default function Home() {
  return (
    <ApolloProvider client={client}>
      <ArticleCards></ArticleCards>
    </ApolloProvider>
  );
}

在一个(粗略制作的)文章列表组件中进行实时更新。

如果您使用了useQuery,请将其替换为useSubscription。
除了gql代码之外,其他部分没有特别变化,因此不作解释。

import { useSubscription } from '@apollo/react-hooks'
import Card from "@material-ui/core/Card";
import CardActions from "@material-ui/core/CardActions";
import CardContent from "@material-ui/core/CardContent";
import Button from "@material-ui/core/Button";
import Typography from "@material-ui/core/Typography";
import articleStyle from '../styles/ArticleCards.module.css';

import { ARTICLES_SUBSCRIPTIONS } from '../gql/articles';

interface ArticleType {
  id: string;
  text: string;
}

const Article = (article: ArticleType) => {
  return (
    <Card variant="outlined" className={articleStyle.card}>
      <CardContent>
        <Typography variant="body2" component="p">
          {article.text}
        </Typography>
      </CardContent>
      <CardActions>
        <Button size="small">MORE</Button>
      </CardActions>
    </Card>
  );
}

const ArticleCards = () => {
  const { loading, error, data} = useSubscription(ARTICLES_SUBSCRIPTIONS);
  console.log(data)
  // ローディング中の表示
  if (loading) return <p>loading</p>
  // エラー時の表示
  if (error) return <p>{error.toString()}</p>
  // 成功してデータが帰ってきた時の表示
  return (
    <div className={articleStyle.article}>
      {data.articles.map((article: ArticleType) => (
        <Article {...article} key={article.id}></Article>
      ))}
    </div>
  );
}

export default ArticleCards

使用GQL编写订阅的方式

我已经写好了查询(query)、订阅(subscription)、变更(mutation)。

import gql from "graphql-tag";

export const ARTICLES_QUERY = gql`
  query {
    articles {
      id
      text
    }
  }
`;

export const ARTICLES_SUBSCRIPTIONS = gql`
  subscription ArticlesSubscriptions {
    articles(limit: 30, order_by: { created_at: asc }) {
      date
      id
      text
    }
  }
`;

export const ADD_ARTICLES = gql`
  mutation AddArticles($text: String = "", $date: date = "") {
    insert_articles(objects: { text: $text, date: $date }) {
      returning {
        id
        text
        date
      }
    }
  }
`;

请阅读此文章

Hasura/GraphQL/React.js/订阅
https://hasura.io/learn/graphql/react/subscriptions/1-subscription/

Hasura/GraphQL/Vue.js/Subscriptions 在这个链接中让你学习如果使用Vue.js在GraphQL中进行订阅。

WebSocket是什么?https://www.keicode.com/script/html5-websocket-1.php

广告
将在 10 秒后关闭
bannerAds