iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0

今天我們來讓 App 具備基本的 UI 以及新增、輸出記錄的相關功能。

UI 設置

筆者預期會有兩個區塊,每個區塊會有一個按鈕,按下去以後會觸發特定的動作。

這兩個按鈕分別是:

  1. 新增記錄
  2. 匯出記錄

讓我們進到 App.js 中,將預設的 Scrollview 段落改為:

 <ScrollView
        contentInsetAdjustmentBehavior="automatic"
        style={backgroundStyle}>
        <View
          style={{
            backgroundColor: isDarkMode 
            ? Colors.black 
            : Colors.white,
          }}>
          <Section title={'Annoyance Notification'} />
          <Section title="記錄關門聲">
            <Button title="點我" onPress={storeTimeRecord} />
          </Section>
          <Section title="輸出檔案">
            <Button title="點我" onPress={getAllStoredRecords} />
          </Section>
          <Section title="清除所有儲存資料(開發用)">
            <Button title="確定點我?" onPress={clearAll} />
          </Section>
        </View>
      </ScrollView>

筆者為了後續資料處理邏輯的開發方便,暫時增加第三個按鈕,以清除所有本地資料,待開發完成後再刪除此區塊。

完成後我們 UI 會長這樣:

https://ithelp.ithome.com.tw/upload/images/20221010/201413573HB8dvKqzh.png


儲存功能

筆者原先想要使用 SQLite,但在調查的過程中發現 React Native 有自身獨特的 API:AsyncStorage,便想趁此次機會試試看。

但打開官方的文件一看,AsyncStorage 的 API 已經 Deprecated了。於是我們進一步調查,找到 stackoverflow 的這篇,推測我們安裝這個套件可以達到類似的效果:@react-native-async-storage/async-storage

讓我們安裝套件後在 App.js 中 import 進來:

import AsyncStorage from '@react-native-async-storage/async-storage';

上述三個按鈕分別對應的 function,讓我們依次建立:

storeTimeRecord

const storeTimeRecord = async () => {
  const now = new Date();
  // Monday: 1
  const weekday = now.getDay();
  const preciseHour = now.getHours();
  const preciseMin = now.getMinutes();
  const year = now.getFullYear();
  const month = now.getUTCMonth() + 1;
  const formattedMonth = month < 10 ? `0${month}` : month;
  const date = now.getDate();

  // eg. 20221010
  const key = `${year}${formattedMonth}${date}`;
  const value = {
    preciseTime: `${preciseHour}:${preciseMin}`,
    weekday,
  };

  // TODO: implementation of deviation field

  try {
    await AsyncStorage.setItem(key, JSON.stringify(value));
    Alert.alert('record stored');
  } catch (e) {
    console.error(e);
  }
};

因為 value 是 object 的關係,我們必須先透過 JSON.stringify 轉換成字串後才能順利存入。

此次先處理具體時間+日期+星期幾的欄位,待預測的時間的通知建立後,此段會再加入新的欄位處理方式。

getAllStoredRecords

const getAllStoredRecords = async () => {
  let keys = [];
  try {
    keys = await AsyncStorage.getAllKeys();
  } catch (e) {
    console.log(e);
  }

  const records = await Promise.all(
    keys.map(async key => {
      const value = await getData(key);
      return {key, value};
    }),
  );

  const message = JSON.stringify(records);
  // TODO: export, not just display
  Alert.alert(message);
};

這邊的做法是取得目前本地 AsyncStorage 儲存的所有 key,然後再透過 getData 取得所有 key 對應的 value。

因為時間關係,筆者今天只處理到將所有儲存的資料印出來。

clearAll

const clearAll = async () => {
  try {
    await AsyncStorage.clear();
  } catch (e) {
    console.log(e);
  }

  Alert.alert('All data cleared');
};

如果出現錯誤以下錯誤:

Error: Requiring module "node_modules/@react-native-async-storage/async-storage/src/index.ts", which threw an exception: Error: [@RNC/AsyncStorage]: NativeModule: AsyncStorage is null.

記得要重新 build:

npx react-native start

再重新啟動虛擬機並且執行:

npx react-native run-android

讓我們看一下執行成果:

儲存資料:
https://ithelp.ithome.com.tw/upload/images/20221010/201413579x4OGwripn.png

讀取資料:
https://ithelp.ithome.com.tw/upload/images/20221010/20141357WkCaiOBeKA.png

今天收工!

延伸閱讀

async-storage 相關


上一篇
實作: Mobile App 的技術選擇
下一篇
實作:Cronjob 技術調查 & 引入套件
系列文
預測惱人的人事物:跟我一起學習如何用資料分析來避開他們38
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言