Зачем и когда использовать Redux Persist?
Redux Persist используется для сохранения состояния вашего Redux-хранилища в AsyncStorage (для React Native) или LocalStorage (для веба). Это полезно в тех случаях, когда вы хотите, чтобы:
- Вход пользователя сохранялся между сессиями.
- Настройки приложения (например, тема или язык) не сбрасывались при перезапуске.
- Состояние корзины покупок или других временных данных оставалось доступным.
Представьте Redux Persist как пункт сохранения в вашей игре. Вы можете выйти в любой момент, а спустя время вернуться к текущему прогрессу без необходимости начинать всё сначала.
Основы Redux Persist
Прежде чем приступить, давайте разберёмся с ключевыми понятиями Redux Persist:
- Хранилище (storage): это место, где Redux Persist будет сохранять данные. Для React Native мы используем
AsyncStorage, который предоставляется в пакете@react-native-async-storage/async-storage. - persistReducer: это обёртка для вашего редьюсера. Она добавляет функциональность сохранения и восстановления состояния.
- persistStore: это объект, который синхронизирует данные между Redux и выбранным хранилищем.
- rehydration: процесс восстановления состояния из хранилища при запуске приложения.
Настройка Redux Persist
Шаг 1: установка зависимостей
Для начала установим Redux Persist и AsyncStorage:
npm install redux-persist @react-native-async-storage/async-storage
Или, если вы используете Yarn:
yarn add redux-persist @react-native-async-storage/async-storage
Шаг 2: импортируем необходимые модули
В файле, где настроен ваш store (например, store.ts), импортируйте нужные модули:
import AsyncStorage from '@react-native-async-storage/async-storage';
import { persistReducer, persistStore } from 'redux-persist';
import { configureStore } from '@reduxjs/toolkit';
import { combineReducers } from 'redux';
Шаг 3: настройка хранилища (storage)
Теперь создадим конфигурацию для Redux Persist:
const persistConfig = {
key: 'root', // Ключ, под которым будет сохраняться состояние
storage: AsyncStorage, // Указываем AsyncStorage
whitelist: ['user'], // Список редьюсеров, которые нужно сохранять
};
Здесь:
key: 'root'— используется для обозначения главного "ключа" в хранилище.storage: AsyncStorage— указывает, где сохранять данные.whitelist— список редьюсеров, которые нужно сохранить. Если вы хотите исключить некоторые данные, используйтеblacklist.
Шаг 4: обёртываем редьюсеры
Создадим редьюсеры и обернём их в persistReducer:
const rootReducer = combineReducers({
user: userReducer, // Редьюсер для информации о пользователе
settings: settingsReducer, // Пример другого редьюсера
});
const persistedReducer = persistReducer(persistConfig, rootReducer);
Теперь persistedReducer знает, какие данные необходимо сохранять.
Шаг 5: создание и настройка Store
Обновим конфигурацию store:
export const store = configureStore({
reducer: persistedReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false, // Отключаем проверки сериализуемости для корректной работы
}),
});
// Создаём persistStore
export const persistor = persistStore(store);
Шаг 6: подключаем Redux Persist в приложение
Обновим корневой файл приложения (например, App.tsx), чтобы подключить Provider и PersistGate:
import React from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import { store, persistor } from './store';
import AppNavigator from './AppNavigator'; // Ваши экраны/навигация
export default function App() {
return (
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<AppNavigator />
</PersistGate>
</Provider>
);
}
Здесь:
Providerоборачивает приложение, предоставляя доступ к Redux-хранилищу.PersistGateгарантирует, что приложение не начнёт рендериться, пока состояние не будет восстановлено из AsyncStorage.
Практический пример: сохранение данных пользователя
Шаг 1: создаем простой редьюсер
Создадим редьюсер для сохранения данных пользователя:
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
interface UserState {
isLoggedIn: boolean;
name: string | null;
}
const initialState: UserState = {
isLoggedIn: false,
name: null,
};
const userSlice = createSlice({
name: 'user',
initialState,
reducers: {
login(state, action: PayloadAction<string>) {
state.isLoggedIn = true;
state.name = action.payload;
},
logout(state) {
state.isLoggedIn = false;
state.name = null;
},
},
});
export const { login, logout } = userSlice.actions;
export default userSlice.reducer;
Шаг 2: подключаем состояние пользователя к приложению
Теперь мы можем использовать useSelector и useDispatch в компонентах, чтобы взаимодействовать с состоянием:
import React from 'react';
import { View, Text, Button } from 'react-native';
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from './store'; // Убедитесь, что указали тип корневого состояния
import { login, logout } from './features/userSlice';
export default function UserProfile() {
const user = useSelector((state: RootState) => state.user);
const dispatch = useDispatch();
return (
<View>
{user.isLoggedIn ? (
<>
<Text>Привет, {user.name}!</Text>
<Button title="Выйти" onPress={() => dispatch(logout())} />
</>
) : (
<Button title="Войти" onPress={() => dispatch(login('Александр'))} />
)}
</View>
);
}
Шаг 3: проверяем сохранение состояния
Закройте и перезапустите приложение. Вы заметите, что состояние пользователя (например, логин) осталось неизменным.
Типичные ошибки и особенности при работе с Redux Persist
Работая с Redux Persist, важно помнить о следующих нюансах:
- При использовании
blacklistилиwhitelistубедитесь, что все редьюсеры корректно указаны. - Если
PersistGateне отображает данные сразу, проверьте правильность настройкиpersistStore. - Убедитесь, что сериализуемость данных в состоянии соблюдена. Redux Persist может выдать неожиданные ошибки, если вы пытаетесь сохранить что-то, что не может быть сериализовано (например, функции или классы).
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ