使用相同的操作清除并重置本地存储中用户的 JWT 令牌

Posted

技术标签:

【中文标题】使用相同的操作清除并重置本地存储中用户的 JWT 令牌【英文标题】:Clear and reset user's JWT token in local storage with same action 【发布时间】:2021-11-19 03:39:10 【问题描述】:

我正在制作一个组件,用户可以在其中更改他们的详细信息,而我这样做的方式是他们实质上是在删除他们的帐户并重新创建它 - 使用 Redux 和 JWT 进行此操作。如果有更好的方法,请告诉我,但现在这对我来说是个窍门。

当用户首次创建帐户时,它会在本地存储中使用正确的详细信息设置其 JWT 令牌。这很好用。当他们登录时,它也设置它没有问题。

问题在于,当他们调用“编辑”功能,删除他们的帐户并创建一个新帐户时,上述情况并没有发生。因此,如果我使用用户名“aaa”创建一个帐户,应用程序会使用配置文件的键和我创建的值来显示该帐户。但是当我调用编辑它时 - 例如用户名“bbb”,即使一个新帐户 is 成功创建(显示在我的 MongoDB 中,可以登录),它是 not 正确更新令牌 - 键的值显示为 的空对象。

有没有一种简单的方法来清除然后更新我丢失的令牌?很想帮忙!

我的行动在这里:

import * as api from "../api";
import  AUTH, DELETE  from "./ActionTypes";

export const signin = (formData, history) => async (dispatch) => 
  try 
    const  data  = await api.signIn(formData)

    dispatch( type: AUTH, data )

    history.push("/");
   catch (error) 
    console.log(error);
  
;

export const signup = (formData, history) => async (dispatch) => 
  try 
    const  data  = await api.signUp(formData)
    
    dispatch( type: AUTH, data )

    history.push("/");
   catch (error) 
    console.log(error);
  
;


export const editProfile = (formData, history) => async (dispatch) => 
  try 

    const  data  = await api.editProfile(formData)
    const  data2  = await api.signUp(formData)

    Promise.resolve(dispatch( type: DELETE, data )).then(
    () => dispatch( type: AUTH, data2 ))

    history.push("/profile");

   catch (error) 
    console.log("error here", error);
  
;

我的减速器在这里:

import  AUTH, LOGOUT, EDIT, REFRESH  from "../actions/ActionTypes";

const authReducer = (state =  authData: null , action) => 
  switch (action.type) 
    case AUTH:
      localStorage.setItem('profile', JSON.stringify(...action?.data));

      return ...state, authData: action.data;
      break;
    case LOGOUT:
    
        localStorage.clear()
        return ...state, authData: null;

      return state;
      break;

    case EDIT:

      localStorage.clear()
      return ...state, authData: null;

    default:
      return state;
      break;
  
;

export default authReducer;

我的项目的 GitHub 在这里:https://github.com/gordonmaloney/lingr-mern/

(顺便说一句,在放弃并来到 Stack Overflow 询问之前,我花了一整天的时间试图弄清楚如何修补细节,但是当我输入我的问题时,我突然意识到我可以尝试通过删除和重新创建来做到这一点,我现在非常接近将它放在我想要的地方,最后这个小颠簸真的让我感到沮丧!)

【问题讨论】:

【参考方案1】:

你在这里有一点 Promises 眩晕。让我们探索editProfile函数,特别是这个位:

Promise.resolve(dispatch( type: DELETE, data )).then(/* ... */)

我会在Promise.resolve()引用文档:

Promise.resolve() 方法返回一个已解析的 Promise 对象 给定值

dispatch() 本身返回一个Promise。所以,你在这里所做的是将dispatch 返回的一个promise 包装成另一个promise,立即通过调用Promise.resolve() 解决这个“外部”promise,然后你正在调度AUTH 动作。

你应该做的是:

dispatch( type: DELETE, data )).then(() => dispatch( type: AUTH, data2 ));

或者,在我看来更好读:

await dispatch( type: DELETE, data );

await dispatch( type: AUTH, data2 );

history.push("/profile");

这意味着您将等待dispatch 完成,然后调用第二次调度。

【讨论】:

嗯,这对我来说是同样的事情 - 它仍然成功地删除了旧帐户并创建了一个新帐户,但是在它运行之后 localStorage 仍然像以前一样显示 。 如果你根本不给dispatch( type: DELETE )打电话怎么办?看起来 dispatch( type: AUTH, data2 ) 应该为您解决问题,因为它会重写 localStorage 上的数据 我刚刚解决了问题 - 导致问题的是“data2”,所以我对其进行了更改,因此在 AUTH 操作和编辑操作中它被称为相同,现在它工作得很好,尽管我怀疑如果不进行您最初建议的更改就不会发生,所以非常感谢您!【参考方案2】:

我解决了!

这是因为两个 reducer 都在寻找 action.data,这就是最初调用注册操作的方式。但是因为它在作为编辑操作的一部分被调用时被称为“data2”,所以它没有找到任何可以更新令牌的东西。我更改了名称,现在它可以正常工作了。

供参考,新代码如下:

动作:

import * as api from "../api";
import  AUTH, DELETE  from "./ActionTypes";

export const signin = (formData, history) => async (dispatch) => 
  try 
    const  data  = await api.signIn(formData)

    dispatch( type: AUTH, data )

    history.push("/");
   catch (error) 
    console.log(error);
  
;

export const signup = (formData, history) => async (dispatch) => 
  try 
    const  data  = await api.signUp(formData)
    
    dispatch( type: AUTH, data )

    history.push("/");
   catch (error) 
    console.log(error);
  
;


export const editProfile = (formData, history) => async (dispatch) => 
  try 

    const  data2  = await api.editProfile(formData)
    const  data  = await api.signUp(formData)

    await dispatch( type: DELETE, data2 );

    await dispatch( type: AUTH, data );

    history.push("/profile");

   catch (error) 
    console.log(error);
  
;

减速器:

import  AUTH, LOGOUT, EDIT, REFRESH  from "../actions/ActionTypes";

const authReducer = (state =  authData: null , action) => 
  switch (action.type) 
    case AUTH:
      localStorage.setItem('profile', JSON.stringify(...action?.data));

      console.log(action)

      return ...state, authData: action.data;
      break;

    case LOGOUT:
    
        localStorage.clear()
        return ...state, authData: null;
      break;

    case EDIT:

      localStorage.clear()
      localStorage.setItem('profile', JSON.stringify(...action?.data2));
      return ...state, authData: null;

    default:
      return state;
      break;
  
;

export default authReducer;

【讨论】:

以上是关于使用相同的操作清除并重置本地存储中用户的 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章

使用 JWT 获取用户信息

Apollo 客户端:在清除或重置存储时保留/重置默认值

使用 jwt 结构重置密码

如何在本地存储中使用 JWT 来保持用户登录?

如何清除 vuex 商店中的状态?

在 JavaScript 中清除本地存储