Reactjs 使用Express GraphQL和React Apollo订阅GraphQL
我遵循Apollo的文档在客户端和服务器上都设置了GraphQL订阅,虽然我有90%在那里,但我不知道如何设置订阅通道以及如何将突变连接到这些通道,以便每当发生突变时,服务器都将新数据推送到客户端。(对于内容,我正在制作一个Reddit克隆,人们在其中发布主题,其他人对此进行评论。因此,当您看到“主题”或“主题列表”时,请将其视为帖子。) 到目前为止,我已成功为订阅设置了Apollo客户端:Reactjs 使用Express GraphQL和React Apollo订阅GraphQL,reactjs,express,publish-subscribe,graphql,apollo,Reactjs,Express,Publish Subscribe,Graphql,Apollo,我遵循Apollo的文档在客户端和服务器上都设置了GraphQL订阅,虽然我有90%在那里,但我不知道如何设置订阅通道以及如何将突变连接到这些通道,以便每当发生突变时,服务器都将新数据推送到客户端。(对于内容,我正在制作一个Reddit克隆,人们在其中发布主题,其他人对此进行评论。因此,当您看到“主题”或“主题列表”时,请将其视为帖子。) 到目前为止,我已成功为订阅设置了Apollo客户端: const wsClient = new SubscriptionClient('ws://localh
const wsClient = new SubscriptionClient('ws://localhost:3001/subscriptions', {
reconnect: true
});
const networkInterface = createNetworkInterface({
uri: '/graphql',
opts: {
credentials: 'same-origin'
}
});
const networkInterfaceWithSubscriptions = addGraphQLSubscriptions(
networkInterface,
wsClient,
);
const client = new ApolloClient({
networkInterface: networkInterfaceWithSubscriptions,
dataIdFromObject: o => o.id
});
我还为订阅设置了后端。这是我的server.js文件:
//===========================================================
//Subscription Managaer
//===========================================================
const pubsub = new PubSub();
const subscriptionManager = new SubscriptionManager({
schema: schema,
pubsub: pubsub
});
//=====================================
//WebSocket + Express Server
//=====================================
const server = createServer(app);
//setup listening port
server.listen(3001, ()=>{
new SubscriptionServer(
{
subscriptionManager: subscriptionManager,
onConnect: (connectionParams, webSocket) => {
console.log('Websocket connection established');
},
onSubscribe: (message, params, webSocket) => {
console.log("The client has been subscribed", message, params);
},
onUnsubsribe: (webSocket) => {
console.log("Now unsubscribed");
},
onDisconnect: (webSocket) => {
console.log('Now disconnected');
}
},
{
server: server,
path: '/subscriptions',
});
console.log('Server is hot my man!');
})
我知道这些都是成功的,因为我在终端中记录了“Websocket连接已建立”消息
接下来是实际订阅-我创建了一个订阅模式类型(就像查询和突变):
并将其合并到我的根模式中。因此,当我签出GraphiQL时,我看到:这个订阅在Docs侧菜单中可用
在我的React组件中,我使用Apollo的subscribeToMore方法成功地“订阅”了它:
const TOPICS_SUBSCRIPTION = gql`
subscription OnTopicAdded($repoFullName: String){
topicAdded(repoFullName: $repoFullName){
id
}
}
`;
class TopicList extends Component {
componentDidMount() {
this.createMessageSubscription = this.props.data.subscribeToMore({
document: TOPICS_SUBSCRIPTION,
// updateQuery: (previousState, {subscriptionData}) => {
// const newTopic = subscriptionData.data.Topic.node
// const topics = previousState.findTopics.concat([newTopic])
// return {
// findTopics: topics
// }
// },
onError: (err) => console.error(err)
})
} //...
我的终端会收到“客户端已订阅”的消息。但这就是我被困的地方。我已经读过SubscriptionManager的SetupFunction,但是Apollo的文档中没有包含它。我找不到如何将“createTopic”变异映射到这个订阅,这样每当有人添加新主题时,它就会在TopicList中弹出
我意识到这真的很长,但我一直在想下一步该怎么做。任何帮助都将不胜感激!!谢谢你的阅读 是,您缺少设置功能。你可以看看这个链接或者这个 工作原理: 首先,您需要发布更改数据的通道。在您的情况下,它可能如下所示:
const manager=new sub.SubscriptionManager({
模式,
pubSub,
设置功能:{
topicAdded:(选项,参数)=>({//graphQL订阅的名称
topicAddedChannel:{//pubsub发布标记的名称
过滤器:(主题)=>{
console.log(topic);//如果有订阅的客户端,则应始终显示新主题
return true;//您可能需要添加筛选器。可能是针对来宾用户或其他用户
},
},
}),
},
});代码>谢谢你!但是,即使在我尝试添加新注释之前,我在控制台中也会遇到以下错误:uncaughtypeerror:无法读取WebSocket.client.onmessage中未定义的属性“handler”,以及:onSubscribe返回的参数无效!返回值必须是一个对象!“为了更多的参考,这里是我的addTopic变体(在一个代码笔中,因为我不能在这里设置字符限制):我仍然可以添加主题,但我必须执行常规操作并刷新页面以使其显示在列表上。有什么想法吗?订阅定义看起来不错。TopicType
是否已定义?在您的情况下,您可以删除args参数,因为您没有要传递给订阅的参数。因此可以删除它这里const TOPICS\u SUBSCRIPTION=gql SUBSCRIPTION OnTopicAdded{topicAdded{id};
我并不清楚第一个错误,但是您可以在组件willreceiveprops(newProps)中添加订阅
函数,然后检查订阅查询是否已加载,我刚才在代码链接中看到,您正在设置一个新的pubsub()
。在这里,您必须使用添加到subscriptionManager中的相同内容
const TOPICS_SUBSCRIPTION = gql`
subscription OnTopicAdded($repoFullName: String){
topicAdded(repoFullName: $repoFullName){
id
}
}
`;
class TopicList extends Component {
componentDidMount() {
this.createMessageSubscription = this.props.data.subscribeToMore({
document: TOPICS_SUBSCRIPTION,
// updateQuery: (previousState, {subscriptionData}) => {
// const newTopic = subscriptionData.data.Topic.node
// const topics = previousState.findTopics.concat([newTopic])
// return {
// findTopics: topics
// }
// },
onError: (err) => console.error(err)
})
} //...