我正在尝试使用Apollo客户端提取我的用户信息并遇到此问题:
我有这个Container
组件,负责在呈现用户数据(而非身份验证)后将其提取。用户可能已登录,也可能未登录,查询返回viewer = null
或viewer = {...usersProps}
。
容器发出请求const { data, refetch } = useQuery<Viewer>(VIEWER);
,成功接收响应并将其保存在我用来从中读取data
并将其设置为当前用户的.viewer
属性中。
然后,用户可以注销,一旦这样做,我便清除了Container
的用户属性setUser(undefined)
(以下代码中未显示,并不重要)。
当我尝试重新登录时发生了问题:调用refetch
会触发graphql
http请求,但是由于它返回的数据与上一次初始登录时返回的数据相同-{{1} }会忽略它,并且不会更新useQuery()
。好吧,从技术上讲不可能有更新,数据是一样的。因此,我的代码data
没有第二次执行,并且用户卡在了登录页面上。
setUser(viewer);
具有相同响应的查询被忽略几乎是有道理的,所以我尝试了不同的方法,使用了回调:
const { data, refetch } = useQuery<Viewer>(VIEWER);
const viewer = data && data.viewer;
useEffect(() => {
if (viewer) {
setUser(viewer);
}
}, [ viewer ]);
在这里,我完全希望Apollo使用相同的数据调用 const { refetch } = useQuery<Viewer>(VIEWER, {
onCompleted: data => {
if (data.viewer) {
setUser(data.viewer);
}
}
});
回调……但是它不会那样做。因此,我对此颇为困惑-如何使Apollo对查询的onCompleted
做出反应,以便可以在refetch
的状态下重新填充user
?
答案 0 :(得分:0)
在这种情况下,阿波罗的缓存非常方便。 客户
import { resolvers, typeDefs } from './resolvers';
let cache = new InMemoryCache()
const client = new ApolloClient({
cache,
link: new HttpLink({
uri: 'http://localhost:4000/graphql',
headers: {
authorization: localStorage.getItem('token'),
},
}),
typeDefs,
resolvers,
});
cache.writeData({
data: {
isLoggedIn: !!localStorage.getItem('token'),
cartItems: [],
},
})
LoginPage
const IS_LOGGED_IN = gql`
query IsUserLoggedIn {
isLoggedIn @client
}
`;
function IsLoggedIn() {
const { data } = useQuery(IS_LOGGED_IN);
return data.isLoggedIn ? <Pages /> : <Login />;
}
onLogin
function Login() {
const { data, refetch } = useQuery(LOGIN_QUERY);
let viewer = data && data.viewer
if (viewer){
localStorage.setItem('token',viewer.token)
}
// rest of the stuff
}
onLogout
onLogout={() => {
client.writeData({ data: { isLoggedIn: false } });
localStorage.clear();
}}
有关本地状态管理的更多信息。检出this。
希望这会有所帮助!