我如何在 react-native 聊天应用程序中使用 GraphQl 订阅从 GraphQl 查询中获取实时更新

Posted

技术标签:

【中文标题】我如何在 react-native 聊天应用程序中使用 GraphQl 订阅从 GraphQl 查询中获取实时更新【英文标题】:How can i use GraphQl subscriptions in react-native chat application to get real-time updates from GraphQl queries 【发布时间】:2020-09-22 23:33:38 【问题描述】:

我在 react-native 聊天应用程序中使用 GraphQl API。当另一个用户向我发送消息而不刷新 API 时,我想获得实时更新。如何在 react-native 中使用 GraphQl API 使用 GraphQl 订阅或 Websocket?

我应该为订阅和普通 API 使用不同的 URL 吗?

这是我的 config.js

import  ApolloClient  from 'apollo-client';
import  createHttpLink  from 'apollo-link-http';
import  WebSocketLink  from 'apollo-link-ws';
import  HttpLink  from 'apollo-boost';
import  setContext  from 'apollo-link-context';
import  InMemoryCache  from 'apollo-cache-inmemory';
import  AsyncStorage  from 'react-native';

// const httpLink = createHttpLink(
//     uri: 'https://graphql.chat.dev.com/graphql',
// );

// const link = new HttpLink(
//    uri: `https://graphql.chat.dev.com/graphql`,
//    headers: 
//      Authorization: AsyncStorage.getItem('@user_token');
//    
//  );

 const link = new WebSocketLink(
  uri: `wss://graphql.chat.dev.com/graphql`,
  options: 
    reconnect: true,
    connectionParams: 
      headers: 
        Authorization: AsyncStorage.getItem('@user_token');
      
    
  
)

const defaultOptions = 
  query: 
    fetchPolicy: "network-only",
    errorPolicy: "all"
  
;

const client = new ApolloClient(
    link: link,
    cache: new InMemoryCache(),
    defaultOptions
);

export default client;

【问题讨论】:

【参考方案1】:

我没有用 React Native 实现 Apollo,但我用我的 React 应用程序实现了。根据我的经验,您应该为订阅和普通 API 使用不同的 URL。然后,使用import split from 'apollo-link'来拆分链接,这样就可以给每个链接发送数据了 取决于发送的操作类型。您可以在 Apollo here 中阅读有关订阅的更多信息。 这是我的client.js 文件。希望对您有所帮助。

import  ApolloClient  from 'apollo-client'
import  createUploadLink  from 'apollo-upload-client'
import  InMemoryCache  from 'apollo-cache-inmemory'
import  setContext  from 'apollo-link-context'
import  split  from 'apollo-link'
import  WebSocketLink  from 'apollo-link-ws'
import  getMainDefinition  from 'apollo-utilities'

const getToken = () => localStorage.getItem('AUTH_TOKEN')
const APOLLO_SERVER ="APOLLO_SERVER url"
const APOLLO_SOCKET ="APOLLO_SOCKET url"

// Create an http link:
const httpLink = createUploadLink(
	uri: APOLLO_SERVER,
	credentials: 'same-origin',
)

const authLink = setContext((_,  headers ) => 
	const token = getToken()
	return 
		headers: 
			...headers,
			authorization: token ? `Bearer $token` : '',
		,
	
)

// Create a WebSocket link:
const wsLink = new WebSocketLink(
	uri: APOLLO_SOCKET,
	options: 
		reconnect: true,
		connectionParams: 
			Authorization: getToken() ? `Bearer $getToken()` : '',
		,
	,
)

// using the ability to split links, you can send data to each link
// depending on what kind of operation is being sent
const link = split(
	// split based on operation type
	( query ) => 
		const definition = getMainDefinition(query)
		return (
			definition.kind === 'OperationDefinition' &&
			definition.operation === 'subscription'
		)
	,
	wsLink,
	authLink.concat(httpLink)
)

const cache = new InMemoryCache()

const client = new ApolloClient(
	cache,
	link,
	typeDefs,
	resolvers,
)

这是我将查询与订阅集成的组件:

import React,  useEffect  from 'react'
import  useQuery  from '@apollo/react-hooks'
import gql from 'graphql-tag'
...

// query for querying message list
const GET_MESSAGE_LIST = gql`...`
// subscription for listening new message
const ON_MESSAGE_CREATED = gql`...`

const ChatView = props => 
  const  data, loading, subscribeToMore  = useQuery(GET_MESSAGE_LIST, 
    
			notifyOnNetworkStatusChange: true,
			variables: 
				query: 
					limit: 10,
					userId: props.userId,
				,
			,
		
  )
  
  useEffect(() => 
    subscribeToMore(
			document: ON_MESSAGE_CREATED,
			variables:   filter:  userId: props.userId   ,
			shouldResubscribe: true,
			updateQuery: (prev,  subscriptionData ) => 
				let newMessage = subscriptionData.data.onZaloMessageCreated
				
				return Object.assign(, prev, 
					messageList: 
						...prev.messageList,
						items:
							prev.messageList.items.filter(
								item => item.id === newMessage.id
							).length === 0
								? [newMessage, ...prev.messageList.items]
								: prev.messageList.items,
					,
				)
			,
		)
  , [subscribeToMore])
  
  return ...

【讨论】:

你能给我一个示例如何在聊天应用程序中将查询与订阅集成? @PratapPenmetsa 我已经更新了我的答案。希望对您有所帮助。

以上是关于我如何在 react-native 聊天应用程序中使用 GraphQl 订阅从 GraphQl 查询中获取实时更新的主要内容,如果未能解决你的问题,请参考以下文章

如何正确处理聊天消息应用程序的“读取” - “未读”状态?

如何正确处理聊天消息应用程序的“已读”-“未读”状态?

react-native FlatList 滚动到底部的聊天应用程序

TextInput 在 react-native 中隐藏在键盘后面

react-native聊天室|RN版聊天App仿微信实例|RN仿微信界面

脚本在 WebView 中不适用于 react-native