التخزين المحلي — أساسيات React Native
التخزين المحلي في React Native
1. AsyncStorage
npm install @react-native-async-storage/async-storage
// npx expo install @react-native-async-storage/async-storage
import AsyncStorage from '@react-native-async-storage/async-storage';
// حفظ قيمة نصية
await AsyncStorage.setItem('username', 'أحمد');
// حفظ كائن
const user = { name: 'أحمد', age: 25 };
await AsyncStorage.setItem('user', JSON.stringify(user));
// قراءة قيمة
const username = await AsyncStorage.getItem('username');
// قراءة كائن
const userJSON = await AsyncStorage.getItem('user');
const savedUser = userJSON ? JSON.parse(userJSON) : null;
// حذف قيمة
await AsyncStorage.removeItem('username');
// حذف كل البيانات
await AsyncStorage.clear();
// الحصول على كل المفاتيح
const keys = await AsyncStorage.getAllKeys();
// عمليات متعددة
await AsyncStorage.multiSet([
['key1', 'value1'],
['key2', 'value2'],
]);
const values = await AsyncStorage.multiGet(['key1', 'key2']);
Custom Hook للـ AsyncStorage
import { useState, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
function useStorage(key, initialValue) {
const [value, setValue] = useState(initialValue);
const [loading, setLoading] = useState(true);
useEffect(() => {
loadValue();
}, []);
const loadValue = async () => {
try {
const stored = await AsyncStorage.getItem(key);
if (stored !== null) {
setValue(JSON.parse(stored));
}
} catch (error) {
console.error('Error loading:', error);
} finally {
setLoading(false);
}
};
const saveValue = async (newValue) => {
try {
setValue(newValue);
await AsyncStorage.setItem(key, JSON.stringify(newValue));
} catch (error) {
console.error('Error saving:', error);
}
};
const removeValue = async () => {
try {
setValue(initialValue);
await AsyncStorage.removeItem(key);
} catch (error) {
console.error('Error removing:', error);
}
};
return { value, saveValue, removeValue, loading };
}
// الاستخدام
function SettingsScreen() {
const { value: settings, saveValue: setSettings, loading } = useStorage('settings', {
darkMode: false,
notifications: true,
language: 'ar',
});
if (loading) return <ActivityIndicator />;
return (
<View>
<Switch
value={settings.darkMode}
onValueChange={(value) =>
setSettings({ ...settings, darkMode: value })
}
/>
</View>
);
}
2. Expo SecureStore (للبيانات الحساسة)
npx expo install expo-secure-store
import * as SecureStore from 'expo-secure-store';
// حفظ Token
await SecureStore.setItemAsync('authToken', 'your-secret-token');
// قراءة Token
const token = await SecureStore.getItemAsync('authToken');
// حذف Token
await SecureStore.deleteItemAsync('authToken');
// خيارات إضافية
await SecureStore.setItemAsync('pin', '1234', {
keychainAccessible: SecureStore.WHEN_UNLOCKED,
});
3. MMKV (أسرع بكثير)
npm install react-native-mmkv
import { MMKV } from 'react-native-mmkv';
const storage = new MMKV();
// حفظ
storage.set('username', 'أحمد');
storage.set('age', 25);
storage.set('isLoggedIn', true);
// قراءة
const username = storage.getString('username');
const age = storage.getNumber('age');
const isLoggedIn = storage.getBoolean('isLoggedIn');
// حذف
storage.delete('username');
// التحقق من وجود مفتاح
const exists = storage.contains('username');
// كل المفاتيح
const keys = storage.getAllKeys();
// مسح الكل
storage.clearAll();
4. مثال تطبيقي: نظام Auth كامل
// services/authStorage.js
import * as SecureStore from 'expo-secure-store';
import AsyncStorage from '@react-native-async-storage/async-storage';
const AUTH_TOKEN_KEY = 'auth_token';
const USER_DATA_KEY = 'user_data';
export const AuthStorage = {
// Token (آمن)
async setToken(token) {
await SecureStore.setItemAsync(AUTH_TOKEN_KEY, token);
},
async getToken() {
return await SecureStore.getItemAsync(AUTH_TOKEN_KEY);
},
async removeToken() {
await SecureStore.deleteItemAsync(AUTH_TOKEN_KEY);
},
// User Data (عادي)
async setUser(user) {
await AsyncStorage.setItem(USER_DATA_KEY, JSON.stringify(user));
},
async getUser() {
const data = await AsyncStorage.getItem(USER_DATA_KEY);
return data ? JSON.parse(data) : null;
},
async removeUser() {
await AsyncStorage.removeItem(USER_DATA_KEY);
},
// تسجيل خروج كامل
async logout() {
await Promise.all([
this.removeToken(),
this.removeUser(),
]);
},
};
// الاستخدام في Context
function AuthProvider({ children }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
loadUser();
}, []);
const loadUser = async () => {
try {
const token = await AuthStorage.getToken();
if (token) {
const userData = await AuthStorage.getUser();
setUser(userData);
}
} finally {
setLoading(false);
}
};
const login = async (email, password) => {
const response = await api.post('/login', { email, password });
await AuthStorage.setToken(response.token);
await AuthStorage.setUser(response.user);
setUser(response.user);
};
const logout = async () => {
await AuthStorage.logout();
setUser(null);
};
return (
<AuthContext.Provider value={{ user, login, logout, loading }}>
{children}
</AuthContext.Provider>
);
}
اختبر فهمك