带有 GraphQL Apollo 客户端的订阅组件
Posted
技术标签:
【中文标题】带有 GraphQL Apollo 客户端的订阅组件【英文标题】:Subscription component with GraphQL Apollo Client 【发布时间】:2019-01-18 12:59:43 【问题描述】:我有一个订阅的应用程序已经在使用 subscribeToMore
查询组件:
<Query query=GET_MESSAGES>
( data, subscribeToMore ) =>
return (
<MessageList
messages=data.allMessages
subscribeToMore=subscribeToMore/>
);
</Query>
该查询加载了一个消息列表,据我所知,我们将订阅者附加到 ComponentDidMount 中,因此每当我在查询内的列表中添加新元素时,我的订阅将监听订阅并执行我想要的任何操作(在这种情况下,将新消息添加到我当前的消息列表中)。
消息组件列表:
export default class MessageList extends React.Component
componentDidMount()
this.props.subscribeToMore(
document: MESSAGE_CREATED,
updateQuery: (prev, subscriptionData ) =>
if (!subscriptionData.data) return prev;
return
allMessages: [
subscriptionData.data.messageCreated,
...prev.allMessages
],
;
,
);
render()
return (
<div>
this.props.messages.map(message => (
<MessageElement key=message.id
message=message/>
))
</div>
);
我想添加另一个订阅,所以如果我编辑我的消息,信息会实时更新。为了实现这一点,我使用 Subscription
创建了以下组件消息组件(我想根据更新的消息添加另一个订阅)
export default class MessageElement extends Component
componentDidMount()
this.messageUpdatedSubscription();
messageUpdatedSubscription = () => (
<Subscription
subscription=MESSAGE_UPDATED>
( data: messageUpdated ) => (
console.log('Do smthg???',messageUpdated)
)
</Subscription>
);
render()
return(
<Mutation mutation=UPDATE_MESSAGE key=this.props.message.id>
updateMessage => (
<div>
<div>this.props.message.text</div>
<div>
<Star active=this.props.message.isFavorite
onClick=() => updateMessage( variables:
id: this.props.message.id,
text:this.props.message.text,
isFavorite:!this.props.message.isFavorite );
/>
</div>
</div>
)
</Mutation>);
我在服务器上的订阅正在工作,因为我已经在 Query 上订阅了 MESSAGE_CREATED,并且我已经在服务器上测试了我对 MESSAGE_UPDATED 的订阅已被触发。但是,我无法弄清楚为什么 UI 没有显示或 console.log 任何内容,就好像它没有收听订阅一样。
我可以通过订阅组件或 subscribeToMore 来实现吗?
提前致谢
【问题讨论】:
【参考方案1】:无法在 ComponentDidMount 中启动订阅组件。它必须驻留在 render() 生命周期方法中。它的参数可以在 ComponentDidMount 中使用,但不能在组件中使用。
我能想到 3 种可能的解决方案:
1) 您可以尝试将 Subscription 方法放入您的渲染方法中。您只需要将它嵌套在 Mutation 组件的内部或外部。
2) 您可以在该组件的父组件中启动订阅组件,并将其参数(messageUpdate)向下传递给组件 MessageElement。然后,您可以在 ComponentDidMount 中使用 props 的 messageUpdate。
3) 你可以使用 Apollo 的高阶组件。然后你可以在 props 中访问 messageUpdate。 (免责声明 - 我之前没有尝试过)。
我希望这会有所帮助!
【讨论】:
谢谢@cory-mcaboy。我最终通过将我的订阅嵌套到我的突变中来解决您的第一个建议。【参考方案2】:根据@cory-mcaboy 的建议,我将订阅嵌套到突变中。 我还发现,因为我有一个消息列表,我只想根据我正在更新的消息而不是整个列表来触发订阅;我必须通过以下方式在后端和前端修改我的订阅:
服务器架构
const typeDefs = gql` type Subscription
messageUpdated(id: Int!): Message`;
服务器解析器
Subscription:
messageUpdated:
subscribe: withFilter(
() => pubsub.asyncIterator([MESSAGE_UPDATED]),
(payload, variables) =>
return payload.messageUpdated.id === variables.id;
,
),
,
客户端组件
const MESSAGE_UPDATED = gql` subscription messageUpdated($id: Int!)
messageUpdated(id:$id)
id
text
isFavorite
`;
export default class MessageElement extends Component
render()
return(<Mutation mutation=UPDATE_MESSAGE key=this.props.message.id>
updateMessage => (
<div>
<div>this.props.message.text</div>
<Subscription subscription=MESSAGE_UPDATED
variables= id: this.props.message.id >
() =>
return <Star active=this.props.message.isFavorite
onClick=() => updateMessage( variables:
id: this.props.message.id,
text: this.props.message.text,
isFavorite: !this.props.message.isFavorite );/>
</Subscription>
</div>
)
</Mutation>
);
您可以在以下repo中看到代码:后端itr-apollo-server,前端itr-apollo-client
【讨论】:
以上是关于带有 GraphQL Apollo 客户端的订阅组件的主要内容,如果未能解决你的问题,请参考以下文章
使用带有 React 和 Apollo 的 graphql 订阅制作实时应用程序
Rails、Graphql、Apollo 客户端的 Auth Token 无效
带有 Vertx 订阅的 Apollo GraphQL 失败