今日關鍵字:Async Storage
App常常會有需要在自己的手機中儲存的狀況
以我的App來說
需要記住使用者把那些資料夾到我的最愛中
否則每次打開我的最愛都會是空的
這次使用的是Async Storage
react-native現在把一些不一定會用到的模組分出來,讓開發者有需要再自行安裝
而Async Storage也是一樣的情形
yarn add @react-native-community/async-storage
cd ios && pod install && cd ..
使用方式當然還是要慣例地先來看一下官方教學
import AsyncStorage from '@react-native-community/async-storage';
// Storing string value
const storeData = async (value) => {
try {
await AsyncStorage.setItem('@storage_Key', value)
} catch (e) {
// saving error
}
}
// Storing object value
const storeData = async (value) => {
try {
const jsonValue = JSON.stringify(value)
await AsyncStorage.setItem('@storage_Key', jsonValue)
} catch (e) {
// saving error
}
}
// Reading string value
const getData = async () => {
try {
const value = await AsyncStorage.getItem('@storage_Key')
if(value !== null) {
// value previously stored
}
} catch(e) {
// error reading value
}
}
// Reading object value
const getData = async () => {
try {
const jsonValue = await AsyncStorage.getItem('@storage_Key')
return jsonValue != null ? JSON.parse(jsonValue) : null;
} catch(e) {
// error reading value
}
}
好像除了async
,await
之外跟web的local storage差不多
由於這個App的資料來源預想是從遠端抓取
抓取回來後再比對本地端儲存的資料
有加入我的最愛的就更新isFavorite
的值為true
當每次加入至我的最愛或開啟提醒時都會觸發reducer
這時要趁著reducer整理完資料時進行儲存的動作
這裡只要修改之前更新狀態的reducer
case animeActions.RENEW_DATA:
for (let i = 0; i < state.length; i += 1) {
if (action.payload!.anime!.id === allAnimeCopy[i].id) {
allAnimeCopy[i] = action.payload!.anime!
}
// 挑出開啟提醒或加入我的最愛的資料
if (allAnimeCopy[i].isFavorite || allAnimeCopy[i].isReminding) {
Favorite.push(allAnimeCopy[i])
}
}
// 儲存至我的最愛
storeFavorite(Favorite)
return { ...state, allAnime: allAnimeCopy }
當然還要寫一個函式將資料存進Async Storage
export const storeFavorite = async (Favorite: Array<Anime>) => {
try {
const jsonValue = JSON.stringify(Favorite)
await AsyncStorage.setItem('anime', jsonValue)
} catch (e) {
// saving error
}
}
這裡當然也要有相對應的讀取函式
export const getFavorite = async () => {
try {
const jsonValue = await AsyncStorage.getItem('anime')
return jsonValue !== null ? JSON.parse(jsonValue) : null
} catch (error) {
// error reading value
// console.log(error)
return []
}
}
由於要先從遠端抓取資料後才跟Async Storage裡的資料進行比對
而且getFavorite
也是非同步的
這裡可以在action
的generator function處理
function* getAnime() {
const data = yield call(() => contentPromise.then((result) => result))
// 讀取Async Storage
const favorite = yield call(() => getFavorite().then((result) => result))
// 更新fetch回來資料的屬性
if (
Array.isArray(data) &&
data.length > 0 &&
Array.isArray(favorite) &&
favorite.length > 0
) {
favorite.forEach((anime) => {
for (let i = 0; i < data.length; i += 1) {
if (anime.id === data[i].id) {
data[i].isFavorite = anime.isFavorite
data[i].isReminding = anime.isReminding
break
}
}
})
}
yield put(getAllAnimateSuccess(data))
}
完成後就可以將我的最愛跟加入提醒的清單儲存到本地端了
明天要來把資料放入firebase並且遠端抓取