AuthContext.tsx 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import React, { createContext, ReactNode, useEffect, useReducer } from 'react';
  2. import { TOKEN_KEY, UserInfo, USERINFO_KEY } from '@app/constants';
  3. import { getAllItems, storageApp } from '@common/StorageHelper.ts';
  4. type RequiredUserInfo = Required<UserInfo>;
  5. type AuthState = {
  6. loading: boolean;
  7. token?: string; // token
  8. userInfo?: RequiredUserInfo; // 用户信息
  9. };
  10. type ActionMap = {
  11. retrieve: { token: string; userInfo: RequiredUserInfo } | undefined; // 应用启动取回本地缓存
  12. login: { token: string; userInfo: RequiredUserInfo }; // 登录
  13. logout: undefined; // 退出登录
  14. update: RequiredUserInfo; // 更新用户信息
  15. };
  16. type Action = {
  17. [Key in keyof ActionMap]: {
  18. type: Key;
  19. payload: ActionMap[Key];
  20. };
  21. }[keyof ActionMap];
  22. function reducer(state: AuthState, action: Action): AuthState {
  23. switch (action.type) {
  24. case 'retrieve':
  25. return {
  26. ...state,
  27. loading: false,
  28. token: action.payload?.token,
  29. userInfo: action.payload?.userInfo,
  30. };
  31. case 'login':
  32. return {
  33. ...state,
  34. loading: false,
  35. token: action.payload.token,
  36. userInfo: action.payload.userInfo,
  37. };
  38. case 'logout':
  39. return {
  40. ...state,
  41. loading: false,
  42. token: undefined,
  43. userInfo: undefined,
  44. };
  45. case 'update':
  46. return {
  47. ...state,
  48. loading: false,
  49. userInfo: action.payload,
  50. };
  51. }
  52. }
  53. const initialState = {
  54. loading: true,
  55. token: undefined,
  56. userInfo: undefined,
  57. };
  58. const AuthContext = createContext<
  59. | {
  60. state: AuthState;
  61. dispatch: React.Dispatch<Action>;
  62. }
  63. | undefined
  64. >(undefined);
  65. const AuthProvider = ({ children }: { children: ReactNode }) => {
  66. const [state, dispatch] = useReducer(reducer, initialState);
  67. useEffect(() => {
  68. async function retrieve() {
  69. try {
  70. const values = await getAllItems([
  71. { key: TOKEN_KEY },
  72. { key: USERINFO_KEY },
  73. ]);
  74. if (values[0][1] && values[1][1]) {
  75. const tokenValue = values[0][1];
  76. const userInfoValue = JSON.parse(values[1][1]);
  77. dispatch({
  78. type: 'retrieve',
  79. payload: {
  80. token: tokenValue,
  81. userInfo: { ...userInfoValue, isFirstLogin: false },
  82. },
  83. });
  84. } else {
  85. dispatch({
  86. type: 'retrieve',
  87. payload: undefined,
  88. });
  89. }
  90. } catch {
  91. dispatch({
  92. type: 'retrieve',
  93. payload: undefined,
  94. });
  95. }
  96. }
  97. retrieve();
  98. }, []);
  99. return (
  100. <AuthContext.Provider value={{ state, dispatch }}>
  101. {children}
  102. </AuthContext.Provider>
  103. );
  104. };
  105. export type { AuthState, RequiredUserInfo };
  106. export { AuthContext, AuthProvider };