ApolloGraphQL & React:避免在组件重新挂载时调用查询和订阅?
ApolloGraphQL & React: Avoid Calling Query & Subscription When Component Re-Mounts?
我有一个像这样设置的 React 路由器:
<ApolloProvider client={ApolloClient}>
<Router history={browserHistory}>
<React.Suspense fallback={<p></p>}>
<ErrorBoundary>
<AppStateProvider>
<Route render={(routeProps) =>
<TopNav
history={routeProps.history}
match={routeProps.match}
/>
}/>
<Switch>
<Route exact path="/" render={(routeProps) =>
<myComponent history={routeProps.history} match={routeProps.match}
/>
}/>
[.....MORE COMPONENTS.....]
</Switch>
<Route render={(routeProps) =>
<BottomNav history={routeProps.history} match={routeProps.match}
/>
}/>
</AppStateProvider>
</ErrorBoundary>
</React.Suspense>
</Router>
</ApolloProvider>
<TopNav>
组件包含一个 Apollo 查询和订阅:
function TopNav(props) {
[.......]
let unsubscribeFromIncomingMessages = null; <=== re-runs when user changes routes
[.......]
<Query query={INCOMING_MESSAGES_QUERY}
variables={{"localUserId": Meteor.userId()}}>
{({subscribeToMore, loading, error, data, refetch}) => {
if (loading) {
return (
<div key="divLoading"></div>);
} else {
}
if (error) {
return (
<div key="divError"></div>);
}
if (!unsubscribeFromIncomingMessages) {
unsubscribeFromIncomingMessages = subscribeToMore({
document: INCOMING_MESSAGES_SUBSCRIPTION_QUERY,
variables: {
"localUserId": Meteor.userId()
},
updateQuery: (prev, {subscriptionData}) => {
[.....HANDLE UPDATE DATA.....]
}
});
}
return (
<>
</>
);
}}
</Query>
当客户端在我的应用程序中启动另一个路由时,<TopNav>
被重新挂载,这很好,但是 <Query>
和订阅 运行 又重新开始了。
解决这个问题的正确方法是什么?
更新
订阅查询中我的服务器上的断点,每次我导航到客户端上的新页面时都会被命中。
应该发生吗?如果是的话,很好!但如果不是——我想知道。 :)
使变量 unsubscribeFromIncomingMessages
成为全局变量并 在 <Query>
.
上添加 fetchPolicy='cache-first'
编辑:
糟糕,我想我早该预料到这一点。一旦您离开路线,订阅将立即停止,无论您将参考存储在何处。
subscribeToMore
将在您每次进入路线时前往 运行。除非您需要能够停止订阅,否则您不需要记录对它的引用。在入口处设置订阅并不昂贵。
如果您需要在不同的路线上激活相同的订阅,您也需要 运行 在这些路线上进行订阅。
我的理解是订阅不会每次都重新订阅,它只是从上次使用相同变量等的订阅停止的地方开始。
我有一个像这样设置的 React 路由器:
<ApolloProvider client={ApolloClient}>
<Router history={browserHistory}>
<React.Suspense fallback={<p></p>}>
<ErrorBoundary>
<AppStateProvider>
<Route render={(routeProps) =>
<TopNav
history={routeProps.history}
match={routeProps.match}
/>
}/>
<Switch>
<Route exact path="/" render={(routeProps) =>
<myComponent history={routeProps.history} match={routeProps.match}
/>
}/>
[.....MORE COMPONENTS.....]
</Switch>
<Route render={(routeProps) =>
<BottomNav history={routeProps.history} match={routeProps.match}
/>
}/>
</AppStateProvider>
</ErrorBoundary>
</React.Suspense>
</Router>
</ApolloProvider>
<TopNav>
组件包含一个 Apollo 查询和订阅:
function TopNav(props) {
[.......]
let unsubscribeFromIncomingMessages = null; <=== re-runs when user changes routes
[.......]
<Query query={INCOMING_MESSAGES_QUERY}
variables={{"localUserId": Meteor.userId()}}>
{({subscribeToMore, loading, error, data, refetch}) => {
if (loading) {
return (
<div key="divLoading"></div>);
} else {
}
if (error) {
return (
<div key="divError"></div>);
}
if (!unsubscribeFromIncomingMessages) {
unsubscribeFromIncomingMessages = subscribeToMore({
document: INCOMING_MESSAGES_SUBSCRIPTION_QUERY,
variables: {
"localUserId": Meteor.userId()
},
updateQuery: (prev, {subscriptionData}) => {
[.....HANDLE UPDATE DATA.....]
}
});
}
return (
<>
</>
);
}}
</Query>
当客户端在我的应用程序中启动另一个路由时,<TopNav>
被重新挂载,这很好,但是 <Query>
和订阅 运行 又重新开始了。
解决这个问题的正确方法是什么?
更新
订阅查询中我的服务器上的断点,每次我导航到客户端上的新页面时都会被命中。
应该发生吗?如果是的话,很好!但如果不是——我想知道。 :)
使变量 在 unsubscribeFromIncomingMessages
成为全局变量并<Query>
.
fetchPolicy='cache-first'
编辑: 糟糕,我想我早该预料到这一点。一旦您离开路线,订阅将立即停止,无论您将参考存储在何处。
subscribeToMore
将在您每次进入路线时前往 运行。除非您需要能够停止订阅,否则您不需要记录对它的引用。在入口处设置订阅并不昂贵。
如果您需要在不同的路线上激活相同的订阅,您也需要 运行 在这些路线上进行订阅。
我的理解是订阅不会每次都重新订阅,它只是从上次使用相同变量等的订阅停止的地方开始。