saito.k df55be5e19 Merged PR 917: 画面遷移してもインターバルが初期化されないように修正
## 概要
[Task4248: 画面遷移してもインターバルが初期化されないように修正](https://paruru.nds-tyo.co.jp:8443/tfs/ReciproCollection/fa4924a4-d079-4fab-9fb5-a9a11eb205f0/_workitems/edit/4248)

- UpdateTokenTimerを修正
  - F5キーリロードの時もトークンをチェックする
- UpdateTokenTimerを各画面ごとではなくApp.tsxに配置する
  - 画面遷移のたびにSetIntervalが初期化されるのを防ぐ
- 各画面のUpdateTokenTimerを削除
  - App.tsxで管理するため

## レビューポイント
- いかの問題が解消されるかを可能であれば確認してほしい。
  - Dictation画面でトークンのチェック~自動更新ができること
  - 画面遷移をしてもトークンチェックのインターバルが初期化されないこと
  - F5キーリロードをした時にトークンチェックが走ること

## 動作確認状況
- ローカルで確認
- 行った修正がデグレを発生させていないことを確認できるか
  - 具体的にどのような確認をしたか
    - 各画面で取得系の処理が正しく動作することを確認

## 補足
- 相談、参考資料などがあれば
2024-07-02 06:43:41 +00:00

99 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import AppRouter from "AppRouter";
import { BrowserRouter } from "react-router-dom";
import { useMsal } from "@azure/msal-react";
import { useEffect, useLayoutEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import globalAxios, { AxiosError, AxiosResponse } from "axios";
import { clearToken } from "features/auth";
import { useTranslation } from "react-i18next";
import Snackbar from "components/snackbar";
import { selectSnackber } from "features/ui/selectors";
import { closeSnackbar } from "features/ui/uiSlice";
import { UNAUTHORIZED_TO_CONTINUE_ERROR_CODES } from "components/auth/constants";
import { clearUserInfo } from "features/login";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
/*
UpdateTokenTimerをApp.tsxに移動する2024年6月27日
各画面ごとにトークンの期限チェック~自動更新を行う処理を配置していたが、
全画面で共通の処理であることと、画面遷移時にチェックのインターバルがリセットされることを考慮し、App.tsxに移動する。
*/
const App = (): JSX.Element => {
const dispatch = useDispatch();
const { instance } = useMsal();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [t, i18n] = useTranslation();
useEffect(() => {
// すべてのリクエストのヘッダーにX-Requested-Withを追加
globalAxios.interceptors.request.use((config) => {
// headersがあれば追加、なければ新規作成
config.headers = config.headers || {};
// X-Requested-Withを追加
config.headers["X-Requested-With"] = "XMLHttpRequest";
return config;
});
const id = globalAxios.interceptors.response.use(
(response: AxiosResponse) => response,
(e: AxiosError<{ code?: string }>) => {
if (
e?.response?.status === 401 &&
e?.response?.data?.code &&
!UNAUTHORIZED_TO_CONTINUE_ERROR_CODES.includes(e.response.data.code)
) {
dispatch(clearToken());
dispatch(clearUserInfo());
instance.logoutRedirect({
postLogoutRedirectUri: "/?logout=true",
});
}
return Promise.reject(e);
}
);
const cleanup = () => {
globalAxios.interceptors.response.eject(id);
};
return cleanup;
}, [dispatch, instance]);
// Language読み取り
useLayoutEffect(() => {
const { cookie } = document;
if (cookie) {
const cookieArray = cookie.split(";");
const language = cookieArray.find((x) =>
// 先頭の空白を削除してから判定
x.trim().startsWith("language=")
);
if (language) {
i18n.changeLanguage(language.split("=")[1]);
}
}
}, [i18n]);
const snackbarInfo = useSelector(selectSnackber);
return (
<>
<Snackbar
isOpen={snackbarInfo.isOpen}
level={snackbarInfo.level}
message={t(snackbarInfo.message)}
duration={snackbarInfo.duration}
onClose={() => {
dispatch(closeSnackbar());
}}
/>
<BrowserRouter>
<AppRouter />
<UpdateTokenTimer />
</BrowserRouter>
</>
);
};
export default App;