## 概要 [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キーリロードをした時にトークンチェックが走ること ## 動作確認状況 - ローカルで確認 - 行った修正がデグレを発生させていないことを確認できるか - 具体的にどのような確認をしたか - 各画面で取得系の処理が正しく動作することを確認 ## 補足 - 相談、参考資料などがあれば
99 lines
3.2 KiB
TypeScript
99 lines
3.2 KiB
TypeScript
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;
|