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 でタイムアウト設定を解除しておく