ストレージの消去と移行戦略
multiRemoveとclearを使って選択的または全体のキャッシュ消去を行い、アプリ更新間でのストレージスキーマ変更に対応するバージョン管理された移行戦略を実装します
「ストレージの消去と移行戦略」はCoddyKit上の無料React Native Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはReact Native Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 React Native Academyコースには全4レッスンが含まれています。
このレッスンの一部はまだ翻訳されておらず、英語で表示されています。
Why Storage Maintenance Matters
As your app evolves across versions, the data structure you store in AsyncStorage may change. Old data from previous app versions might not match what the new code expects, leading to crashes or incorrect behavior. A solid storage maintenance strategy — including selective clearing and versioned migrations — is essential for apps that have real users with existing data.
Removing Specific Keys with multiRemove
AsyncStorage.multiRemove accepts an array of key strings and deletes all of them in a single operation. This is more efficient than calling removeItem repeatedly in a loop. Use it when a user action should clear a specific subset of data — for example removing all cached API responses without touching user preferences.
async function clearCache() {
const cacheKeys = [
'posts_cache',
'comments_cache',
'user_feed_cache',
];
try {
await AsyncStorage.multiRemove(cacheKeys);
console.log('Cache cleared');
} catch (err) {
console.error('Failed to clear cache:', err);
}
}Clearing All App Data with clear
AsyncStorage.clear() removes all keys stored by the app. Use this only for destructive operations like a factory reset or during development when you need a clean slate. In production, always confirm with the user before calling clear() because it cannot be undone and deletes everything — preferences, cached data, and auth tokens alike.
async function factoryReset() {
await AsyncStorage.clear();
// Reset in-memory state too
useAuthStore.getState().logout();
useSettingsStore.getState().reset();
navigation.reset({ index: 0, routes: [{ name: 'Onboarding' }] });
}Finding Keys to Remove Dynamically
When you store data with dynamic keys (like post_123, post_456), use getAllKeys to find them and filter by a prefix before passing the matching keys to multiRemove. This pattern is useful for clearing all cached pages from a paginated feed without hardcoding each key.
async function clearPostsCache() {
const allKeys = await AsyncStorage.getAllKeys();
const postKeys = allKeys.filter((key) => key.startsWith('post_'));
if (postKeys.length > 0) {
await AsyncStorage.multiRemove(postKeys);
console.log('Cleared', postKeys.length, 'cached posts');
}
}What Is a Storage Migration?
A storage migration upgrades stored data from one schema version to a newer one. When you release a new app version that changes how data is stored — for example renaming a key or adding a required field — migrating existing users' data prevents crashes and data loss. Migrations run once on startup and mark the completion with a version flag.
Versioning Your Storage Schema
Store a schema version number in AsyncStorage alongside your data. On startup, read this version number and compare it to the current expected version. If they differ, run the appropriate migration steps, then update the stored version number. Future launches skip the migration because the versions match.
const CURRENT_VERSION = 3;
const VERSION_KEY = 'storage_version';
async function getStorageVersion(): Promise<number> {
const v = await AsyncStorage.getItem(VERSION_KEY);
return v ? parseInt(v, 10) : 0; // 0 means fresh install or pre-versioning
}
async function setStorageVersion(version: number) {
await AsyncStorage.setItem(VERSION_KEY, String(version));
}Writing a Migration Function
Write a migration function that handles each version upgrade step. Use a switch statement or a series of if checks that fall through from the stored version up to the current version. Each case applies the changes needed to advance one version, so a user upgrading from v1 to v3 runs both the v1-to-v2 and v2-to-v3 migrations in sequence.
async function runMigrations(fromVersion: number) {
if (fromVersion < 1) {
// v0 → v1: rename 'user_name' key to 'username'
const old = await AsyncStorage.getItem('user_name');
if (old) {
await AsyncStorage.setItem('username', old);
await AsyncStorage.removeItem('user_name');
}
}
if (fromVersion < 2) {
// v1 → v2: add default 'fontSize' to settings
const json = await AsyncStorage.getItem('settings');
if (json) {
const settings = JSON.parse(json);
if (!settings.fontSize) settings.fontSize = 'medium';
await AsyncStorage.setItem('settings', JSON.stringify(settings));
}
}
await setStorageVersion(CURRENT_VERSION);
}Running Migrations on App Start
Call the migration logic in your root component's useEffect before anything else reads from storage. This ensures all data is in the expected shape before any screen tries to use it. Keep migrations idempotent — running them twice on the same data should produce the same result to handle edge cases like interrupted writes.
useEffect(() => {
async function init() {
const version = await getStorageVersion();
if (version < CURRENT_VERSION) {
await runMigrations(version);
}
// Now safe to load data — migration is complete
await loadAppData();
setAppReady(true);
}
init();
}, []);Expiring Cached Data
Cache data should not live forever. Store a timestamp alongside cached API responses and check whether it has expired when the app starts or when the user navigates to a screen. If expired, delete the cache and fetch fresh data. A helper function that wraps the cache check makes this reusable across all cached endpoints.
const CACHE_TTL_MS = 60 * 60 * 1000; // 1 hour
async function isCacheExpired(key: string): Promise<boolean> {
const tsStr = await AsyncStorage.getItem(key + '_timestamp');
if (!tsStr) return true;
return Date.now() - parseInt(tsStr, 10) > CACHE_TTL_MS;
}
async function setCache(key: string, data: any) {
await AsyncStorage.setItem(key, JSON.stringify(data));
await AsyncStorage.setItem(key + '_timestamp', String(Date.now()));
}Selective Logout: Clearing Only User Data
When a user logs out, clear their personal data (auth token, profile, private cache) but preserve device preferences like theme and language. Use multiRemove with a specific list of keys rather than clear(). This provides a better UX because the user's display preferences are still there when they log back in.
const USER_DATA_KEYS = ['authToken', 'userProfile', 'feed_cache', 'userId'];
async function logout() {
await AsyncStorage.multiRemove(USER_DATA_KEYS);
// Preferences (theme, language) remain intact
navigation.reset({ index: 0, routes: [{ name: 'Login' }] });
}Documenting Your Storage Schema
Maintain a storage schema documentation file in your project that lists every AsyncStorage key, its type, its default value, and which version it was introduced. This is invaluable when writing migrations, debugging storage issues, and onboarding new developers. Treat it like a database schema — update it every time you add, rename, or remove a stored key.
/**
* AsyncStorage Schema v3
* -------------------------
* Key | Type | Since | Description
* authToken | string | v1 | JWT auth token
* username | string | v1 | (was user_name in v0)
* settings | JSON | v1 | { darkMode, notifications, fontSize }
* .fontSize added v2, .language added v3
* storage_version | number | v1 | Current schema version
*/Quick Check
Test your understanding of React Native Mobile Development concepts from this lesson.
Lesson Recap
In this lesson you learned: multiRemove efficiently clears a specific set of keys while leaving others intact, versioned migrations upgrade old stored data when the app schema changes across releases, and expiring cached data with timestamps prevents stale API responses from living in storage indefinitely. Next up we explore camera access with expo-camera.
よくある質問
「ストレージの消去と移行戦略」レッスンは無料ですか?
はい。「ストレージの消去と移行戦略」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、React Native Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 React Native Academyコースには全4レッスンが含まれています。
「ストレージの消去と移行戦略」で何を学びますか?
multiRemoveとclearを使って選択的または全体のキャッシュ消去を行い、アプリ更新間でのストレージスキーマ変更に対応するバージョン管理された移行戦略を実装します ブラウザで直接実行するハンズオンコードでReact Native Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
React Native Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのReact Native Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「ストレージの消去と移行戦略」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このReact Native Academyレッスンでコードを書いて実行できますか?
はい。すべてのReact Native Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- AsyncStorageの読み書き
- JSONオブジェクトの保存とパース
- 永続化される設定画面の構築
- ストレージの消去と移行戦略