首页 > 解决方案 > 使用 useMutations [Apollo/React hooks] 重定向后 useQuery 返回 undefined

问题描述

在我的应用程序中,我有 2 个公共路由(登录和注册页面)和一个 PrivateRoute,它使用 JWT 验证 localStorage 中的“auth-token”是否有效。

在我的注册页面中,我使用“useMutations”挂钩来注册用户。我在 LocalStorage 中设置了一个令牌,并通过反应路由器将我发送到主要组件('/'),即聊天。

我做了一个“我”查询,它需要我的“身份验证令牌”才能从数据库中获取特定用户。

问题是,在用户成功注册后被重定向到聊天后,useMutations 太快并返回未定义。如果我刷新页面,它会完美地获取“我”查询。

我已经尝试在重定向上使用 setTimeout,因为它可能是令牌设置得不够快。但事实并非如此。

我试过使用 useLazyQuery 钩子,但这也没有用。它还需要刷新,因为第一次它也给出了 undefined。


/// my register component ///

const Register = props => {
  const [createUser] = useMutation(CREATE_USER, {
    onCompleted({ createUser }) {
      localStorage.setItem('auth-token', createUser.token);
      props.history.push('/');
    }
  });

  return (
    <InputWrapper>
      <h2>Signup for DevChat</h2>
      {/* {error !== null && <Alert>{error}</Alert>} */}

      <Formik
        initialValues={{
          userName: '',
          email: '',
          password: '',
          confirmPassword: ''
        }}
        validationSchema={RegisterSchema}
        onSubmit={(values, { resetForm }) => {
          createUser({ variables: values });
          resetForm({
            userName: '',
            email: '',
            password: '',
            confirmPassword: ''
          });
        }}
      >


const UserPanel = () => {
  const { data, loading, error } = useQuery(GET_LOGGED_IN_USER, {
    context: localStorage.getItem('auth-token')
  });

  const [toggleOn, setToggleOn] = useState(false);

  const handleSignOut = () => {
    localStorage.removeItem('auth-token');
    ///refresh page should redirect to /login
    window.location.reload();
  };

  const toggleDropDown = () => {
    setToggleOn(!toggleOn);
  };

  return (
    <ProfileWrapper>
      {loading ? <span>Loading ...</span> : console.log(data)}

      <ProfileGroup onClick={toggleDropDown}>
        <ProfileIcon className='fas fa-user' />
        <ProfileTitle>
          {/* {loading && called ? <span>Loading ...</span> : console.log(data)} */}
          {error ? console.log(error) : null}
        </ProfileTitle>
        <DropDownIcon
          className={toggleOn ? 'fas fa-chevron-up' : 'fas fa-chevron-down'}
        />


/// my console.log(the first time)
undefined
UserPanel.js:95 Error: GraphQL error: jwt malformed

UserPanel.js:91 {}

/// my console.log() after a refresh:

{me: {…}}
me:
age: null
email: "test@gmail.com"
id: "599c5f9a-f97e-4964-a707-138c2159cff8"
userName: "Test"
__typename: "User"
__proto__: Object

想知道我做错了什么...在此先感谢您的帮助和阅读本文... :)

伯特

编辑 1:设置超时在 'props.history.push('/')' 上不起作用

编辑 2:找到解决方案。因为这是我第一个使用 GraphQL 和 Apollo 的项目,所以我不知道 Apollo Boost 就像create-react-app来自 Apollo 的一样,我需要使用Apollo-Client(更可定制的包)来配置所有东西。我按照此处的官方文档Apollo Boost进行了从客户端的迁移。

标签: reactjsreact-router-domreact-apolloapollo-clientgraphql-js

解决方案


它可能与我的客户端设置有关吗?它使用 apollo-boost 包而不是 apollo-client ...


import React from 'react';
import {
  BrowserRouter as Router,
  Switch,
  Route,
  withRouter
} from 'react-router-dom';
import { ApolloProvider } from '@apollo/react-hooks';
import ApolloClient, { InMemoryCache } from 'apollo-boost';
import Login from './components/auth/Login';
import Register from './components/auth/Register';
import Chat from './components/pages/Chat';
import PrivateRoute from './components/auth/PrivateRoute';

// const cache = new InMemoryCache();

const client = new ApolloClient({
  uri: 'http://localhost:4000/',
  headers: {
    Authorization: `Bearer ${localStorage.getItem('auth-token')}`
  }
});

const App = () => {
  return (
    <ApolloProvider client={client}>
      <Router>
        <Switch>
          <PrivateRoute exact path='/' component={Chat} />
          <Route path='/register' component={Register} />
          <Route path='/login' component={Login} />
        </Switch>
      </Router>
    </ApolloProvider>
  );
};

const RootWithAuth = withRouter(App);

推荐阅读