【问题标题】:How to persist data using Apollo?如何使用 Apollo 持久化数据?
【发布时间】:2021-10-29 13:23:26
【问题描述】:

我有一个 Apollo 客户端和一个带有 React 应用程序的服务器,用户可以在其中登录。这是用于登录的 Apollo 服务器突变:

  loginUser: async (root, args) => {
    const theUser = await prisma.user.findUnique({
      where: {email: String(args.email)},
    });
    if (!theUser) throw new Error('Unable to Login');
    const isMatch = bcrypt.compareSync(args.password, theUser.password);
    if (!isMatch) throw new Error('Unable to Login');
    return {token: jwt.sign(theUser, 'supersecret'), currentUser: theUser};
  },

这会返回一个 JWT 和正在登录的用户。

在我的 React 应用程序中,我有一个登录组件:

// Login.tsx

  const [loginUserRes] = useMutation(resolvers.mutations.LoginUser);

  const handleSubmit = async (e) => {
    e.preventDefault();
    const {data} = await loginUserRes({variables: {
      email: formData.email,
      password: formData.password,
    }});
    if (data) {
      currentUserVar({
        email: data.loginUser.currentUser.email,
        id: data.loginUser.currentUser.id,
        loggedIn: true,
      });
      window.localStorage.setItem('token', data.loginUser.token);
    }
  };

此函数将表单数据传递给LoginUser 突变,如果认证成功则返回数据。然后我有一个名为 currentUserVar 的反应变量,我将用户的电子邮件和 ID 存储在其中,以便我可以在整个应用程序中使用它。最后,我将 JWT 存储在 LocalStorage 中,以便发送它以进行授权:

// index.tsx

const authLink = setContext((_, {headers}) => {
  const token = localStorage.getItem('token');
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : '',
    },
  };
});

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache(),
});

一切正常,除了如果用户刷新用户数据消失了,他们必须重新登录,这当然很烦人。

所以我希望得到一些关于如何持久化数据的建议,也许是使用 Apollo?我想我可以添加一个带有 remember me 函数的复选框,该函数将电子邮件和 ID 存储在 LocalStorage 中,当应用程序启动时检查 LocalStorage 中是否有用户数据而不是使用它,但我想知道是否有更好的/其他方法来做到这一点。

【问题讨论】:

    标签: reactjs apollo apollo-client


    【解决方案1】:

    当涉及到登录问题时,您已经为每个请求设置了标头,但是您是否将一个函数传递给 ApolloServer 构造函数来检查每个请求的标头?像这样的:

    const server=new ApolloServer({
      typeDefs,
      resolvers,
      context:async({req})=>{
         const me=getMe(req)
         return {
          models,
          me,
          process.env.SECRET
        }
      }
    })
    
    
    const getMe = async req => {
      const token = req.headers['x-token'];
     
      if (token) {
        try {
          return await jwt.verify(token, process.env.SECRET);
        } catch (e) {
          throw new AuthenticationError(
            'Your session expired. Sign in again.',
          );
        }
      }
    };
    

    至于问题的数据持久化部分,你必须使用setItem将token持久化到locatStorage中。

    【讨论】:

      猜你喜欢
      • 2023-03-19
      • 1970-01-01
      • 2011-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多