AB テストを行うための状態を保存したい。AB テストなので一定時間経過したら A / B の状態をリセットしたい。
同じブラウザなら一定時間同じ状態を表示させたいくらいの要件だったので手っ取り早く localStorage に値を保存したい。期限付きで。
localStorage に期限のオプションはない
localStorage に Cookie や JWT みたいな有効期限のオプションは存在しない。
ABテスト用の state と一緒に有効期限を保存してしまえばよい
const LOCALSTORAGE_KEY = 'keyOfLocalStorage' as const; const EXPIRED_TIME = 1000 * 60 * 60 * 12; // 12h type ABTestType = 'A' | 'B'; interface StorageValue { state: ABTestType; timestamp: number; expiresIn: number; } export const setLocalStorage = (state: ABTestType) => { const timestamp = Date.now(); const saveData: StorageValue = { state, timestamp, expiresIn: timestamp + EXPIRED_TIME; }; localStorage.setItem( LOCALSTORAGE_KEY, JSON.stringify(saveData) ); }
LocalStorage に値が存在しない 又は 値が期限切れの時、新しく localStorage に保存すればOK
localStorage からデータを取得する関数
export const getLocalStorage = (): { state?: ABTestType; isExpired?: boolean; } => { const data = getLocalStorageValue(); if (!data) { return { state: undefined, isExpired: undefined }; } const { state, expiresIn } = data; const isExpired = Date.now() > expiresIn; return { state, isExpired }; } const getLocalStorageValue = () => { const data = localStorage.getItem(LOCALSTORAGE_KEY); // localStorage にデータが存在しない if (data === null) { return undefined; } try { return JSON.parse(data) as StorageValue; // ※ざっくり実装なので as で型を指定してしまう } catch (error) { // localStorage に保存されているデータの形式が不正 return undefined; } }
localStorage に AB テスト用の data が存在しない 又は 期限切れの場合は新しく data を保存する
import { FC, useEffect, useState } from "react"; impoet { getLocalStorage, setLocalStorage } from './storage'; const App: FC = () => { const { state, isExpired } = getLocalStorage(); const [ABState, setABState] = useState<undefined | ABTestType>(state); useEffect(() => { if (isExpired === false) { return; } const newState = (['A', 'B'] as const)[Math.floor(Math.random() * 2)]; setLocalStorage(newState); setABState(newState); }, [isExpired]); return ( <div> {/* ABState が undefined の時は `A` として扱う */} { ABState === 'B' ? <ComponentB /> : <ComponentA /> } </div> ); };
Sample
なんとなくいい感じに動いてるからヨシ!
ここまでやっておいて何だけど、有効期限付きなら Cookie の方が手っ取り早かったかもしれない…
おわり ₍ ᐢ•ᴗ•ᐢ ₎
[参考]
- local storage - How set expiration date to an localStoarge item in Javascript? - Stack Overflow
- ブラウザーのストレージ制限と削除基準 - Web API | MDN
- CookieとLocalStorageについて調べて比較した【JavaScript】 #初心者 - Qiita
- Storage — Jotai, primitive and flexible state management for React
- ReactベースのA/Bテストライブラリreact-ab-testで超簡単にUIのA/Bテストを実現する!