0

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

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

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

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

当我尝试重新登录时出现问题:调用refetch触发graphqlhttp 请求,但由于它返回与上次初始登录期间返回的相同数据 -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以便我可以重新填充userContainer的状态?

4

1 回答 1

2

这是 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();
      }}

有关本地状态管理的更多信息。看看这个

希望这可以帮助!

于 2019-09-23T09:29:13.857 回答