iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 20
0
Modern Web

我不用Expo啦,React Native!系列 第 20

[Day20] 客戶(本地)端儲存

今日關鍵字: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
  }
}

好像除了asyncawait之外跟web的local storage差不多/images/emoticon/emoticon38.gif


由於這個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並且遠端抓取

參考:Async Storage


上一篇
[Day19] 提醒功能-4:計算播放時間
下一篇
[Day21] 資料庫設定
系列文
我不用Expo啦,React Native!33

尚未有邦友留言

立即登入留言