Розроблення списку избранного (Wishlist) в мобільному додатку
Wishlist — функція, яку недооцінюють. Додав товар, закрив додаток, відкрив через тиждень з іншого телефону — список повинен бути там. Проста задача перетворюється на задачу синхронізації, управління конфліктами й оптимістичного UI.
Де зберігати: локально або в хмарі
Залежить від вимог до аутентифікації:
-
Тільки аутентифіковані користувачі: Firestore, PostgreSQL, будь-яка серверна БД. Список прив'язаний до
userId. - Гостьові користувачі + синхронізація при реєстрації: AsyncStorage / MMKV для гостей, при логіні — merge з серверним.
Варіант з merge складніший. Гість міг додати 10 товарів, а його новий акаунт вже має 5 (імпорт з іншого сервісу). Стратегія merge: union двох множин, без дублів по productId.
Оптимістичний UI
Кнопка додавання в wishlist повинна реагувати миттєво — без очікування відповіді сервера. Класична помилка: встановити loading при натиску й заблокувати кнопку на час запиту. Користувач бачить затримку й думає, що не натиснув.
const useWishlist = () => {
const [wishlistIds, setWishlistIds] = useAtom(wishlistAtom);
const toggle = useCallback(async (productId: string) => {
const isAdding = !wishlistIds.has(productId);
// Немедленне зміна UI
setWishlistIds(prev => {
const next = new Set(prev);
isAdding ? next.add(productId) : next.delete(productId);
return next;
});
try {
if (isAdding) {
await api.wishlist.add(productId);
} else {
await api.wishlist.remove(productId);
}
} catch {
// Rollback при помилці
setWishlistIds(prev => {
const next = new Set(prev);
isAdding ? next.delete(productId) : next.add(productId);
return next;
});
Toast.show('Не удалось обновить список избранного');
}
}, [wishlistIds]);
return { wishlistIds, toggle };
};
MMKV для локального кеша
AsyncStorage — повільний. Для wishlist, який читається при кожному рендері карточки товара, використовуємо MMKV (react-native-mmkv). Синхронний read — не потрібен await:
import { MMKV } from 'react-native-mmkv';
const storage = new MMKV({ id: 'wishlist' });
const getLocalWishlist = (): Set<string> => {
const raw = storage.getString('ids');
return raw ? new Set(JSON.parse(raw)) : new Set();
};
const saveLocalWishlist = (ids: Set<string>) => {
storage.set('ids', JSON.stringify([...ids]));
};
Синхронний read з MMKV на main thread — безпечний, операція займає <0.1 мс.
Лічильник у іконці wishlist
Бейдж з числом елементів в wishlist — це похідна від wishlistIds.size. Не робіть окремий запит за лічильником. Якщо wishlist синхронізований — розмір множини вже відомий.
Оцінка
Wishlist з оптимістичним UI, MMKV-кешем і cloud sync (Firestore або REST): 1–2 тижні.







