Apollo useQuery() - 如果响应相同,则忽略“refetch”

Posted

技术标签:

【中文标题】Apollo useQuery() - 如果响应相同,则忽略“refetch”【英文标题】:Apollo useQuery() - "refetch" is ignored if the response is the same 【发布时间】:2020-01-22 15:34:40 【问题描述】:

我正在尝试使用 Apollo-client 来提取我的用户信息并遇到此问题:

我有这个Container 组件负责在呈现用户数据后提取(不是身份验证)。用户可能已登录或未登录,查询返回viewer = nullviewer = ...usersProps

容器发出请求const data, refetch = useQuery<Viewer>(VIEWER);,成功接收响应并将其保存在我用来读取.viewerdata 属性中,并将其设置为我的当前用户。

然后用户可以注销,一旦他们这样做,我清除Container的用户属性setUser(undefined)(没有显示在下面的代码中,不重要)。

当我尝试重新登录时出现问题:调用refetch 触发graphql http 请求,但由于它返回的数据与上次初始登录期间返回的数据相同 - useQuery() 忽略它并且不会更新data。好吧,从技术上讲,不可能有更新,数据是一样的。所以我的代码setUser(viewer); 没有第二次执行,用户卡在登录页面上。

  const  data, refetch  = useQuery<Viewer>(VIEWER);

  const viewer = data && data.viewer;

  useEffect(() => 
    if (viewer) 
      setUser(viewer);
    

  , [ viewer ]);

具有相同响应的查询忽略几乎是有意义的,所以我尝试了不同的方法,使用回调:

  const  refetch  = useQuery<Viewer>(VIEWER, 
    onCompleted: data => 
      if (data.viewer) 
        setUser(data.viewer);
      
    
  );

在这里,我完全希望 Apollo 调用 onCompleted 回调,无论是否使用相同的数据......但它没有这样做。所以我有点坚持这个 - 我如何让 Apollo 对我的查询的 refetch 做出反应,以便我可以在我的 Container 的状态下重新填充 user

【问题讨论】:

【参考方案1】:

这是 apollo 的缓存派上用场的场景。 客户

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: [],
  ,
)

登录页面

const IS_LOGGED_IN = gql`
  query IsUserLoggedIn 
    isLoggedIn @client
  
`;

function IsLoggedIn() 
  const  data  = useQuery(IS_LOGGED_IN);
  return data.isLoggedIn ? <Pages /> : <Login />;

登录

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=() => 
        client.writeData( data:  isLoggedIn: false  );
        localStorage.clear();
      

有关本地状态管理的更多信息。签出this。

希望这会有所帮助!

【讨论】:

以上是关于Apollo useQuery() - 如果响应相同,则忽略“refetch”的主要内容,如果未能解决你的问题,请参考以下文章

当输入变量相同时,Apollo useQuery 不会进行网络调用

apollo 的 useQuery 数据在 client.resetStore() 之后没有更新

@apollo/client 反应钩子 useQuery() 数据未定义

将参数传递给 react-apollo-hooks useQuery

如何防止 Apollo 客户端 useQuery 中的错误传播?

使用 apollo useQuery 时有没有办法禁用 apollo-link-dedup?