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キーリロードをした時にトークンチェックが走ること

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

## 補足
- 相談、参考資料などがあれば
This commit is contained in:
saito.k 2024-07-02 06:43:41 +00:00
parent 35425c576a
commit df55be5e19
13 changed files with 51 additions and 49 deletions

View File

@ -11,6 +11,13 @@ import { selectSnackber } from "features/ui/selectors";
import { closeSnackbar } from "features/ui/uiSlice"; import { closeSnackbar } from "features/ui/uiSlice";
import { UNAUTHORIZED_TO_CONTINUE_ERROR_CODES } from "components/auth/constants"; import { UNAUTHORIZED_TO_CONTINUE_ERROR_CODES } from "components/auth/constants";
import { clearUserInfo } from "features/login"; import { clearUserInfo } from "features/login";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
/*
UpdateTokenTimerをApp.tsxに移動する2024627
App.tsxに移動する
*/
const App = (): JSX.Element => { const App = (): JSX.Element => {
const dispatch = useDispatch(); const dispatch = useDispatch();
@ -82,6 +89,7 @@ const App = (): JSX.Element => {
/> />
<BrowserRouter> <BrowserRouter>
<AppRouter /> <AppRouter />
<UpdateTokenTimer />
</BrowserRouter> </BrowserRouter>
</> </>
); );

View File

@ -1,4 +1,4 @@
import React, { useCallback } from "react"; import React, { useCallback, useLayoutEffect, useState } from "react";
import { AppDispatch } from "app/store"; import { AppDispatch } from "app/store";
import { decodeToken } from "common/decodeToken"; import { decodeToken } from "common/decodeToken";
import { useInterval } from "common/useInterval"; import { useInterval } from "common/useInterval";
@ -17,41 +17,58 @@ import { TOKEN_UPDATE_INTERVAL_MS, TOKEN_UPDATE_TIME } from "./constants";
export const UpdateTokenTimer = () => { export const UpdateTokenTimer = () => {
const dispatch: AppDispatch = useDispatch(); const dispatch: AppDispatch = useDispatch();
const navigate = useNavigate(); const navigate = useNavigate();
// トークンの更新中かどうか
const [isUpdating, setIsUpdating] = useState(false);
const delegattionToken = useSelector(selectDelegationAccessToken); const delegattionToken = useSelector(selectDelegationAccessToken);
// 期限が分以内であれば更新APIを呼ぶ // 期限が分以内であれば更新APIを呼ぶ
const updateToken = useCallback(async () => { const updateToken = useCallback(async () => {
// localStorageからトークンを取得 if (isUpdating) {
const jwt = loadAccessToken(); return;
// 現在時刻を取得
const now = DateTime.local().toSeconds();
// selectorに以下の判定処理を移したかったが、初期表示時の値でしか判定できないのでComponent内に置く
if (jwt) {
const token = decodeToken(jwt);
if (token) {
const { exp } = token;
if (exp - now <= TOKEN_UPDATE_TIME) {
await dispatch(updateTokenAsync());
}
}
} }
setIsUpdating(true);
// 代行操作トークン更新処理 try {
if (delegattionToken) { // localStorageからトークンを取得
const token = decodeToken(delegattionToken); const jwt = loadAccessToken();
if (token) { // 現在時刻を取得
const { exp } = token; const now = DateTime.local().toSeconds();
if (exp - now <= TOKEN_UPDATE_TIME) { // selectorに以下の判定処理を移したかったが、初期表示時の値でしか判定できないのでComponent内に置く
const { meta } = await dispatch(updateDelegationTokenAsync()); if (jwt) {
if (meta.requestStatus === "rejected") { const token = decodeToken(jwt);
dispatch(cleanupDelegateAccount()); if (token) {
navigate("/partners"); const { exp } = token;
if (exp - now <= TOKEN_UPDATE_TIME) {
await dispatch(updateTokenAsync());
} }
} }
} }
// 代行操作トークン更新処理
if (delegattionToken) {
const token = decodeToken(delegattionToken);
if (token) {
const { exp } = token;
if (exp - now <= TOKEN_UPDATE_TIME) {
const { meta } = await dispatch(updateDelegationTokenAsync());
if (meta.requestStatus === "rejected") {
dispatch(cleanupDelegateAccount());
navigate("/partners");
}
}
}
}
} catch (e) {
// eslint-disable-next-line no-console
console.error("Token update error:", e);
} finally {
setIsUpdating(false);
} }
}, [dispatch, delegattionToken, navigate]); }, [isUpdating, delegattionToken, dispatch, navigate]);
useLayoutEffect(() => {
updateToken();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useInterval(updateToken, TOKEN_UPDATE_INTERVAL_MS); useInterval(updateToken, TOKEN_UPDATE_INTERVAL_MS);

View File

@ -1,5 +1,4 @@
import { AppDispatch } from "app/store"; import { AppDispatch } from "app/store";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import Footer from "components/footer"; import Footer from "components/footer";
import Header from "components/header"; import Header from "components/header";
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
@ -106,7 +105,6 @@ const AccountPage: React.FC = (): JSX.Element => {
)} )}
<div className={styles.wrap}> <div className={styles.wrap}>
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div> <div>
<div className={styles.pageHeader}> <div className={styles.pageHeader}>

View File

@ -1,6 +1,5 @@
/* eslint-disable jsx-a11y/control-has-associated-label */ /* eslint-disable jsx-a11y/control-has-associated-label */
import React, { useCallback, useEffect } from "react"; import React, { useCallback, useEffect } from "react";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import { isApproveTier } from "features/auth"; import { isApproveTier } from "features/auth";
import { TIERS } from "components/auth/constants"; import { TIERS } from "components/auth/constants";
import Footer from "components/footer"; import Footer from "components/footer";
@ -166,7 +165,6 @@ export const LicenseOrderHistory: React.FC<LicenseOrderHistoryProps> = (
delegationAccessToken && <DelegationBar /> delegationAccessToken && <DelegationBar />
} }
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div> <div>
<div className={styles.pageHeader}> <div className={styles.pageHeader}>

View File

@ -1,5 +1,4 @@
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import Footer from "components/footer"; import Footer from "components/footer";
import Header from "components/header"; import Header from "components/header";
import styles from "styles/app.module.scss"; import styles from "styles/app.module.scss";
@ -149,8 +148,6 @@ export const LicenseSummary: React.FC<LicenseSummaryProps> = (
> >
{delegationAccessToken && <DelegationBar />} {delegationAccessToken && <DelegationBar />}
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div className=""> <div className="">
<div className={styles.pageHeader}> <div className={styles.pageHeader}>

View File

@ -2,7 +2,6 @@ import React, { useCallback, useState, useEffect } from "react";
import Footer from "components/footer"; import Footer from "components/footer";
import Header from "components/header"; import Header from "components/header";
import styles from "styles/app.module.scss"; import styles from "styles/app.module.scss";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { AppDispatch } from "app/store"; import { AppDispatch } from "app/store";
import { getTranslationID } from "translation"; import { getTranslationID } from "translation";
@ -263,7 +262,6 @@ const PartnerLicense: React.FC = (): JSX.Element => {
{!islicenseOrderHistoryOpen && !isViewDetailsOpen && ( {!islicenseOrderHistoryOpen && !isViewDetailsOpen && (
<div className={styles.wrap}> <div className={styles.wrap}>
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div className=""> <div className="">
<div className={styles.pageHeader}> <div className={styles.pageHeader}>

View File

@ -1,6 +1,5 @@
/* eslint-disable jsx-a11y/control-has-associated-label */ /* eslint-disable jsx-a11y/control-has-associated-label */
import { AppDispatch } from "app/store"; import { AppDispatch } from "app/store";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import Footer from "components/footer"; import Footer from "components/footer";
import Header from "components/header"; import Header from "components/header";
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
@ -169,7 +168,6 @@ const PartnerPage: React.FC = (): JSX.Element => {
/> />
<div className={styles.wrap}> <div className={styles.wrap}>
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div className={styles.pageHeader}> <div className={styles.pageHeader}>
<h1 className={styles.pageTitle}> <h1 className={styles.pageTitle}>

View File

@ -1,6 +1,5 @@
import React from "react"; import React from "react";
import Header from "components/header"; import Header from "components/header";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { getTranslationID } from "translation"; import { getTranslationID } from "translation";
import styles from "styles/app.module.scss"; import styles from "styles/app.module.scss";
@ -12,7 +11,6 @@ const SupportPage: React.FC = () => {
return ( return (
<div className={styles.wrap}> <div className={styles.wrap}>
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div> <div>
<div className={styles.pageHeader}> <div className={styles.pageHeader}>

View File

@ -2,7 +2,6 @@ import React, { useCallback, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { AppDispatch } from "app/store"; import { AppDispatch } from "app/store";
import Header from "components/header"; import Header from "components/header";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { getTranslationID } from "translation"; import { getTranslationID } from "translation";
import undo from "assets/images/undo.svg"; import undo from "assets/images/undo.svg";
@ -69,7 +68,6 @@ export const TemplateFilePage: React.FC = () => {
> >
{delegationAccessToken && <DelegationBar />} {delegationAccessToken && <DelegationBar />}
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div> <div>
<div className={styles.pageHeader}> <div className={styles.pageHeader}>

View File

@ -2,7 +2,6 @@ import React, { useCallback, useEffect, useState } from "react";
import Header from "components/header"; import Header from "components/header";
import Footer from "components/footer"; import Footer from "components/footer";
import styles from "styles/app.module.scss"; import styles from "styles/app.module.scss";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import progress_activit from "assets/images/progress_activit.svg"; import progress_activit from "assets/images/progress_activit.svg";
import undo from "assets/images/undo.svg"; import undo from "assets/images/undo.svg";
import group_add from "assets/images/group_add.svg"; import group_add from "assets/images/group_add.svg";
@ -93,7 +92,6 @@ const TypistGroupSettingPage: React.FC = (): JSX.Element => {
> >
{delegationAccessToken && <DelegationBar />} {delegationAccessToken && <DelegationBar />}
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div> <div>
<div className={styles.pageHeader}> <div className={styles.pageHeader}>

View File

@ -3,7 +3,6 @@ import React, { useCallback, useEffect, useState } from "react";
import Header from "components/header"; import Header from "components/header";
import Footer from "components/footer"; import Footer from "components/footer";
import styles from "styles/app.module.scss"; import styles from "styles/app.module.scss";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { import {
listUsersAsync, listUsersAsync,
@ -153,7 +152,6 @@ const UserListPage: React.FC = (): JSX.Element => {
> >
{delegationAccessToken && <DelegationBar />} {delegationAccessToken && <DelegationBar />}
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div className=""> <div className="">
<div className={styles.pageHeader}> <div className={styles.pageHeader}>

View File

@ -1,4 +1,3 @@
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import Footer from "components/footer"; import Footer from "components/footer";
import Header from "components/header"; import Header from "components/header";
import React, { useCallback, useEffect, useState } from "react"; import React, { useCallback, useEffect, useState } from "react";
@ -138,7 +137,6 @@ const WorktypeIdSettingPage: React.FC = (): JSX.Element => {
> >
{delegationAccessToken && <DelegationBar />} {delegationAccessToken && <DelegationBar />}
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div> <div>
<div className={styles.pageHeader}> <div className={styles.pageHeader}>

View File

@ -2,7 +2,6 @@ import React, { useCallback, useEffect, useState } from "react";
import Header from "components/header"; import Header from "components/header";
import Footer from "components/footer"; import Footer from "components/footer";
import styles from "styles/app.module.scss"; import styles from "styles/app.module.scss";
import { UpdateTokenTimer } from "components/auth/updateTokenTimer";
import ruleAddImg from "assets/images/rule_add.svg"; import ruleAddImg from "assets/images/rule_add.svg";
import templateSettingImg from "assets/images/template_setting.svg"; import templateSettingImg from "assets/images/template_setting.svg";
import worktypeSettingImg from "assets/images/worktype_setting.svg"; import worktypeSettingImg from "assets/images/worktype_setting.svg";
@ -83,7 +82,6 @@ const WorkflowPage: React.FC = (): JSX.Element => {
> >
{delegationAccessToken && <DelegationBar />} {delegationAccessToken && <DelegationBar />}
<Header /> <Header />
<UpdateTokenTimer />
<main className={styles.main}> <main className={styles.main}>
<div className=""> <div className="">
<div className={styles.pageHeader}> <div className={styles.pageHeader}>