我有一个已经使用 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>);
}}
我在服务器上的订阅正在运行,因为我已经在查询中对MESSAGE_CREATED的订阅正常工作,并且我已经测试了在服务器上触发了对我的MESSAGE_UPDATED的订阅。但是,我无法弄清楚为什么UI不显示或console.log好像没有监听订阅一样。
我可以通过订阅组件还是通过SubscribeToMore来实现?
预先感谢
答案 0 :(得分:1)
无法在ComponentDidMount中启动订阅组件。它必须驻留在render()生命周期方法中。它的参数可以在ComponentDidMount中使用,但不能在组件中使用。
我可以想到3种可能的解决方案:
1)您可以尝试将Subscription方法放入渲染方法中。您只需将其嵌套在Mutation组件的内部或外部即可。
2)您可以在该组件的父级中启动订阅组件,并将其参数(messageUpdate)向下传递给组件MessageElement。然后,您可以在ComponentDidMount中使用messageUpdate道具。
3)您可以使用Apollo的高阶组件。然后,您可以在道具中访问messageUpdate。 (免责声明-我之前没有尝试过)。
我希望这会有所帮助!
答案 1 :(得分:1)
基于@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>
);
}}
您可以在以下存储库中查看代码:后端itr-apollo-server,前端itr-apollo-client