如何在React中使用上下文API注销用户

huangapple go评论61阅读模式
英文:

How to logout user in React using context API

问题

我正在使用React hooks并创建了登录注销功能,但现在我想在令牌过期时注销用户。

  • 我在欢迎页面上使用它,在两分钟后,如果我做其他操作并且令牌已过期,我希望注销用户。
  • 我已创建了一个上下文,名为Auth context,其中包含登录注销上下文。
  • 我只想在令牌过期时调用注销函数。

我的authContext

const initialstate = {
  user: null,
};

if (localStorage.getItem("JWT_Token")) {
  const jwt_Token_decoded = Jwt_Decode(localStorage.getItem("JWT_Token"));
  console.log(jwt_Token_decoded.exp * 1000);
  console.log(Date.now());

  if (jwt_Token_decoded.exp * 1000 < Date.now()) {
    localStorage.clear(); // 这仅在刷新页面或路由更改时运行,不起作用
  } else {
    initialstate.user = jwt_Token_decoded;
  }
}

const AuthContext = createContext({
  user: null,
  login: (userData) => {},
  logout: () => {},
});

const AuthReducer = (state, action) => {
  switch (action.type) {
    case "LOGIN":
      return {
        ...state,
        user: action.payload,
      };
    case "LOGOUT":
      return {
        ...state,
        user: null,
      };
    default:
      return state;
  }
};

const AuthProvider = (props) => {
  const [state, dispatch] = useReducer(AuthReducer, initialstate);

  const login = (userData) => {
    localStorage.setItem("JWT_Token", userData.token);
    dispatch({
      type: "LOGIN",
      payload: userData,
    });
  };

  const logout = () => {
    localStorage.clear();
    dispatch({ action: "LOGOUT" });
  };

  return (
    <AuthContext.Provider
      value={{ user: state.user, login, logout }}
      {...props}
    />
  );
};

export { AuthContext, AuthProvider };

在上述代码中,我正在检查令牌的过期情况,但这仅在页面重新加载时运行。在这里,我希望在每次路由更改时运行它,以便可以检查令牌的过期情况。

我不知道如何做到这一点以及在哪里做到这一点。

要注销,我只需调用我的注销上下文函数,但我不明白如何进行调用。

我不知道是否需要在Axios实例中执行某些操作,它是一个单独的文件,如下所示。在这里,我创建一个实例,以便可以在一个地方定义我的标头和其他内容。

// 全局axios实例
import axios, { AxiosHeaders } from "axios";
const BASE_URL = "https://jsonplaceholder.typicode.com"; // 服务器API

export default axios.create({
  baseURL: BASE_URL,
  headers: {
    "Content-Type": "Application/json",
    Access-token: "在此处添加令牌",
  },
});

我该如何解决这个问题?我查看了这个问题,但在这个示例中使用了GraphQL,因此有一个用于设置上下文的函数,我可以传递并使用store来分发注销。

我分享了我的axiosInstance代码,我认为需要添加一些内容。我准备使用任何可以生成中间件的方法,以便可以在一个地方检查令牌。

英文:

I am working with React hooks and created login logout functionality, but now I want user to logout when token is expired.

  • I am on a welcome page and using it, after two minutes if I do something else and the token is expired, I want to logout the user
  • I have created a context, Auth context where I have login logout context
  • I just want to call the logout function whenever the token expires

My authContext

  const initialstate = {
user: null,
};
if (localStorage.getItem(&quot;JWT_Token&quot;)) {
const jwt_Token_decoded = Jwt_Decode(localStorage.getItem(&quot;JWT_Token&quot;));
console.log(jwt_Token_decoded.exp * 1000);
console.log(Date.now());
if (jwt_Token_decoded.exp * 1000 &lt; Date.now()) {
localStorage.clear(); // this runs only when I refresh the page or reload on route change it dosent work
} else {
initialstate.user = jwt_Token_decoded;
}
}
const AuthContext = createContext({
user: null,
login: (userData) =&gt; {},
logout: () =&gt; {},
});
const AuthReducer = (state, action) =&gt; {
switch (action.type) {
case &quot;LOGIN&quot;:
return {
...state,
user: action.payload,
};
case &quot;LOGOUT&quot;:
return {
...state,
user: null,
};
default:
return state;
}
};
const AuthProvider = (props) =&gt; {
const [state, dispatch] = useReducer(AuthReducer, initialstate);
const login = (userData) =&gt; {
localStorage.setItem(&quot;JWT_Token&quot;, userData.token);
dispatch({
type: &quot;LOGIN&quot;,
payload: userData,
});
};
const logout = () =&gt; {
localStorage.clear();
dispatch({ action: &quot;LOGOUT&quot; });
};
return (
&lt;AuthContext.Provider
value={{ user: state.user, login, logout }}
{...props}
/&gt;
);
};
export { AuthContext, AuthProvider };

In the above code I am checking for expiry of token, but that only runs when page reloads, here I want to run it in every route change so that I can check for the token expiry.

I don't know how to do that and where to do that.

To logout I just need to call my logout context function, but I don't understand how to make the call.

I don't know If I have to do something in my Axios instance which is a separate file like below. Here I am creating one instance so that I can define my headers and other stuff at one place.

//global axios instance
import axios, { AxiosHeaders } from &quot;axios&quot;; // import axios from axios
const BASE_URL = &quot;https://jsonplaceholder.typicode.com&quot;; // server api
export default axios.create({
baseURL: BASE_URL,
headers: {
&quot;Content-Type&quot;: &quot;Application/json&quot;,
Access-token: &quot;token here&quot;,
},
});

How can I approach this problem? I checked this question but in this example GraphQL has been used, so there is a function to set context where I can pass and use the store to dispatch my logout.

I have shared my axiosInstance code I think something needs to be added there. I am ready to use any approach that will generate some middleware, so that I can check for token in one place.

答案1

得分: 1

有一些要考虑的要点

  1. 您可以更新注销功能,将用户发送到登录页面,这样可以确保在用户注销时始终出现此行为;
  2. 使用API响应来验证令牌是否过期,这样您就无需一直监视令牌到期的时间并在任何未经授权的API调用后注销用户;
  3. 注意这个 localStorage.clear() 调用,有时它可能清除比您想要的更多,并且始终声明您真正想要清除的内容是个好主意。例如:有时您可能希望在注销后保留用户语言、主题或一些不应在注销后清除的UI配置;
  4. Axios有一个拦截API调用的API,这是在API调用之前/之后执行某些操作的好方法(在任何未经授权的响应后使用它进行注销)
  5. 如果您确实需要通过客户端处理此注销并且不需要等待API响应,可以尝试使用setTimeout方法(不建议)
英文:

There are some points to consider in your approach

  1. You can update the log out function to send the user to the login page, this way you guarantee this behavior whenever this user has been logged out;
  2. Use the API response to validate when your token has expired, this way you don't need to keep watching the time of the token expiration and logout the user after any unauthorized API call;
  3. Pay attention to this localStorage.clear() call, sometimes it can clear more than you want, and it is always a good idea to declare what you really want to clear. Eg.: sometimes you want to keep your user language, theme, or some UI configs that shouldn't be cleared after a logout;
  4. Axios has an API to intercept your API call, this is a good way to do something before/after an API call (use it to logout after any unauthorized response)
  5. If you really need to take care of this logout by the client and don't need to await the API response, you can try the setTimeout method (not recommended)

huangapple
  • 本文由 发表于 2023年2月8日 23:46:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75388280.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定