Введение
Когда пользователь открывает ваше приложение, он ожидает, что оно запомнит его настройки, данные авторизации или язык интерфейса. Например, если пользователь вошел в приложение вчера, мы хотим "вспомнить" его состояние и автоматически залогинить пользователя, а не заставлять его вводить данные повторно.
Здесь и приходит на помощь AsyncStorage. Мы можем сохранить необходимую информацию при закрытии приложения (например, токен авторизации или последние просмотренные товары), а затем загрузить её при следующем запуске.
Инициализация данных из AsyncStorage
Создание функции для извлечения данных
Начнем с создания функции, которая будет извлекать данные. Допустим, мы работаем с авторизацией, и нам нужно "вытянуть" токен, который хранится в AsyncStorage. Используем метод getItem для получения данных.
Пример:
import AsyncStorage from '@react-native-async-storage/async-storage';
const getUserToken = async (): Promise<string | null> => {
try {
// Извлекаем токен пользователя из AsyncStorage по ключу
const token = await AsyncStorage.getItem('userToken');
// Если токен отсутствует, возвращаем null
return token;
} catch (error) {
console.error('Ошибка при извлечении токена:', error);
return null;
}
};
Здесь мы обрабатываем возможные ошибки, чтобы приложение не упало, если, например, AsyncStorage недоступен или данные повреждены. Ошибка будет просто залогирована.
Использование этой функции при запуске
Теперь, чтобы воспользоваться нашей функцией, мы можем использовать хуки React. Например, useEffect прекрасно подходит для выполнения задач при монтировании компонента.
import React, { useEffect, useState } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
const App = () => {
const [loading, setLoading] = useState(true);
const [userToken, setUserToken] = useState<string | null>(null);
useEffect(() => {
const bootstrapAsync = async () => {
const token = await getUserToken();
setUserToken(token);
setLoading(false); // Завершаем загрузку
};
bootstrapAsync();
}, []);
if (loading) {
return (
<View>
<ActivityIndicator size="large" color="#0000ff" />
<Text>Загрузка...</Text>
</View>
);
}
return (
<View>
<Text>{userToken ? `Добро пожаловать, пользователь!` : `Пожалуйста, войдите.`}</Text>
</View>
);
};
export default App;
Здесь теперь отобразится индикатор загрузки, пока приложение извлекает токен пользователя. После завершения загрузки мы показываем либо приветствие, либо сообщение о необходимости войти.
Подгрузка данных для начального состояния приложения
Вместо ручной настройки можно интегрировать извлечение данных из AsyncStorage в глобальное состояние приложения. Например, если вы используете Redux, убедитесь, что начальное состояние вашего Store инициализируется из AsyncStorage.
Пример (используем Redux Toolkit):
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import AsyncStorage from '@react-native-async-storage/async-storage';
interface AuthState {
token: string | null;
isLoading: boolean;
}
const initialState: AuthState = {
token: null,
isLoading: true,
};
const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setToken(state, action: PayloadAction<string | null>) {
state.token = action.payload;
state.isLoading = false;
},
clearToken(state) {
state.token = null;
},
},
});
export const { setToken, clearToken } = authSlice.actions;
export const initializeAuth = () => async (dispatch: any) => {
const token = await AsyncStorage.getItem('userToken');
dispatch(setToken(token));
};
export default authSlice.reducer;
Теперь мы можем вызвать действие initializeAuth при запуске приложения, чтобы настроить начальное состояние приложения.
Использование хуков React для автоматической подгрузки данных
Создадим кастомный хук, который объединит в себе логику инициализации данных из AsyncStorage и немного упростит наш код.
Пример:
import { useState, useEffect } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
const useAsyncStorage = (key: string) => {
const [data, setData] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
const value = await AsyncStorage.getItem(key);
setData(value);
} catch (error) {
console.error(`Ошибка извлечения данных для ключа "${key}":`, error);
}
};
fetchData();
}, [key]);
return data;
};
export default useAsyncStorage;
Теперь мы можем использовать этот хук так:
import useAsyncStorage from './useAsyncStorage';
const App = () => {
const userToken = useAsyncStorage('userToken');
if (userToken === null) {
return <Text>Загрузка...</Text>;
}
return <Text>{userToken ? `Добро пожаловать!` : `Пожалуйста, войдите.`}</Text>;
};
С помощью кастомного хука мы минимизируем повторяющийся код и можем переиспользовать эту логику в любом месте приложения.
Особенности и возможные проблемы
При работе с AsyncStorage важно помнить, что извлечение данных — асинхронный процесс. Это означает, что от него нельзя ожидать мгновенного результата. Именно поэтому мы добавляем состояние загрузки loading, чтобы пользователь понимал, что приложение продолжает работать, а не зависло.
Обратите внимание также на обработку ошибок. Если данные повреждены или отсутствуют, приложение должно уметь gracefully восстановиться. Например, если токен не загрузился, просто выполните выход из системы.
Итоговый сценарий
Давайте представим, что мы работаем с кэшированием профиля пользователя. При старте приложения мы загружаем профиль из AsyncStorage и отображаем его:
import React, { useEffect, useState } from 'react';
import { View, Text, ActivityIndicator } from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
interface UserProfile {
name: string;
email: string;
}
const App: React.FC = () => {
const [profile, setProfile] = useState<UserProfile | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchProfile = async () => {
try {
const profileData = await AsyncStorage.getItem('userProfile');
if (profileData) {
setProfile(JSON.parse(profileData)); // Парсим JSON-строку
}
} catch (error) {
console.error('Ошибка загрузки профиля:', error);
} finally {
setLoading(false);
}
};
fetchProfile();
}, []);
if (loading) {
return <ActivityIndicator size="large" color="#0000ff" />;
}
return (
<View>
{profile ? (
<Text>Имя: {profile.name}, Email: {profile.email}</Text>
) : (
<Text>Данные профиля не найдены.</Text>
)}
</View>
);
};
export default App;
Теперь у нас есть полноценный пример автоматической загрузки данных из AsyncStorage, который можно адаптировать для любой задаче — от кэширования настроек до сохранения токенов. Эффективная работа с локальным хранилищем данных делает приложения более интерактивными и удобными для пользователя.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ