Amplify JavaScript + React で一定期間ユーザー操作が無い場合に Cognito からサインアウトする実装
これは何?
- Amplify JavaScript と React を使用して、一定期間ユーザーの操作が無い場合に Cognito からサインアウトする実装をしてみたメモ
ソースコード
import { Amplify, Auth } from 'aws-amplify';
import { Authenticator } from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import awsExports from './aws-exports';
import { useEffect, useState } from 'react';
Amplify.configure(awsExports);
export default function App() {
    const [timer, setTimer] = useState();
    useEffect(() => {
        const resetTimer = () => {
            if (timer) {
                clearTimeout(timer)
            }
            const newTimer = setTimeout(() => {
                console.log('Timeout!!!!!!!')
                Auth.signOut()
            }, 5000)
            setTimer(newTimer)
        }
        window.addEventListener('mousemove', resetTimer)
        return () => {
            window.removeEventListener('mousemove', resetTimer)
            if (timer) {
                clearTimeout(timer)
            }
        }
    }, [timer])
    return (
        <Authenticator>
            {({ signOut, user }) => (
            <main>
                <h1>Hello {user.username}</h1>
                <button onClick={signOut}>Sign out</button>
            </main>
            )}
        </Authenticator>
    );
}
コード解説
useState
    const [timer, setTimer] = useState();
useState • React
https://beta.reactjs.org/reference/react/useState
- App コンポーネントで使用する state の定義
- ユーザー操作が一定期間無いことをカウントするための timer と、 timer をセットするための setTimer
useEffect
    useEffect(() => {
        const resetTimer = () => {
            if (timer) {
                clearTimeout(timer)
            }
            const newTimer = setTimeout(() => {
                Auth.signOut()
            }, 5000)
            setTimer(newTimer)
        }
        window.addEventListener('mousemove', resetTimer)
        return () => {
            window.removeEventListener('mousemove', resetTimer)
            if (timer) {
                clearTimeout(timer)
            }
        }
    }, [timer])
useEffect • React
https://beta.reactjs.org/reference/react/useEffect
React 観点
- App コンポーネントで動作する Effect の実装
- 第一引数 setup: Effect のロジック
- コンポーネントが DOM に追加されると setup 関数が実行される
- 依存関係を更新して再レンダリングするたびに React によって古い値で cleanup 関数を実行し、新しい値で setup 関数を実行する
- コンポーネントが DOM から削除される際にも cleanup 関数が実行される
- cleanup を行う function を return しても良い
 
- 第二引数 dependencies?: 依存関係
- setup コードで参照される Reactive value のリスト
- props, state, コンポーネントで宣言された変数や関数
- 指定した値が更新された場合に effect が再実行される
 
 
- setup コードで参照される Reactive value のリスト
        const resetTimer = () => {
            if (timer) {
                clearTimeout(timer)
            }
            const newTimer = setTimeout(() => {
                Auth.signOut()
            }, 5000)
            setTimer(newTimer)
        }
        window.addEventListener('mousemove', resetTimer)
        return () => {
            window.removeEventListener('mousemove', resetTimer)
            if (timer) {
                clearTimeout(timer)
            }
        }
setup logic 観点
- resetTimer
- 既存 timer が存在していれば clearTimeout でタイムアウト設定の解除
- newTimer は setTimeout で新しいタイムアウトをセット
- setTimer で newTimer を timer state にセット
 
- addEventListener
- アプリケーションとしてはグローバルなタイムアウトとして利用したいので window に対して addEventListener を行う
- 今回は mousemove イベントを type として登録しているが、何を持ってユーザーの操作が無いとするかはアプリ要件によって異なるので、適宜カスタマイズする感じが無難だと思われる
- 利用可能な Event は MDN でチェックすると良い
- https://developer.mozilla.org/ja/docs/Web/API/Event
 
 
- return
- useEffect における cleanup 処理
- window に対して removeEventListener を行い、既存 timer があれば clearTimeout でタイムアウト設定を解除しておく