iT邦幫忙

2024 iThome 鐵人賽

DAY 19
0
Mobile Development

從零開始學React Native系列 第 19

【從零開始學React Native】18. 創建Todo Tracker——app設置並連接到parse server (上)

  • 分享至 

  • xImage
  •  

今天我們開始在react native設置,並連接到我們的parse server上。

首先我們先安裝套件:

parse @parse/react-native @types/parse

接著創建一個能讓parse使用的storage

// src\utils\mmkvStorage.ts

import { MMKV } from 'react-native-mmkv';

const storage = new MMKV();

export const MMKVStorage = {
  setItem: (key: string, value: string): Promise<void> => {
    return new Promise((resolve) => {
      storage.set(key, value);
      resolve();
    });
  },
  getItem: (key: string): Promise<string | null> => {
    return new Promise((resolve) => {
      const value = storage.getString(key);
      resolve(value);
    });
  },
  removeItem: (key: string): Promise<void> => {
    return new Promise((resolve) => {
      storage.delete(key);
      resolve();
    });
  },
  getAllKeys: (): Promise<string[]> => {
    return new Promise((resolve) => {
      const keys = storage.getAllKeys();
      resolve(keys);
    });
  },
  multiGet: (keys: string[]): Promise<[string, string | null][]> => {
    return new Promise((resolve) => {
      const values = keys
        .filter(k => storage.contains(k))
        .map(k => [k, storage.getString(k)]);
      resolve(values);
    });
  },
  multiRemove: (keys: string[]): Promise<void> => {
    return new Promise((resolve) => {
      keys.forEach(k => storage.delete(k));
      resolve();
    });
  },
};

更新我們的user和task service。

// src\services\user.service.ts

import Parse from 'parse/react-native';
import { User } from '../types';

export const UserService = {
  saveUser: async (user: User) => {
    const currentUser = await Parse.User.current();
    if (currentUser) {
      await currentUser.save(user);
    }
  },

  getUser: async (): Promise<User | null> => {
    const currentUser = await Parse.User.current();
    return currentUser ? currentUser.toJSON() as User : null;
  },

  setLoggedIn: async (isLoggedIn: boolean) => {
    // This is handled by Parse automatically
  },

  isLoggedIn: async (): Promise<boolean> => {
    const currentUser = await Parse.User.current();
    return !!currentUser;
  },

  saveToken: async (token: string) => {
    // This is handled by Parse automatically
  },

  getToken: async (): Promise<string | null> => {
    const currentUser = await Parse.User.current();
    return currentUser ? currentUser.getSessionToken() : null;
  },

  clearUserData: async () => {
    await Parse.User.logOut();
  },

  login: async (email: string, password: string): Promise<User> => {
    const user = await Parse.User.logIn(email, password);
    return user.toJSON() as User;
  },

  logout: async () => {
    await Parse.User.logOut();
  },
};

// src\services\task.service.ts
import Parse from 'parse/react-native';
import { Task } from '../types';

export const TaskService = {
  saveTasks: async (tasks: Task[]) => {
    const TaskObject = Parse.Object.extend('Task');
    const savePromises = tasks.map(task => {
      const taskObject = new TaskObject();
      return taskObject.save(task);
    });
    await Promise.all(savePromises);
  },

  getTasks: async (): Promise<Task[]> => {
    const TaskObject = Parse.Object.extend('Task');
    const query = new Parse.Query(TaskObject);
    const results = await query.find();
    return results.map(result => result.toJSON() as Task);
  },

  getTaskById: async (taskId: string): Promise<Task | undefined> => {
    const TaskObject = Parse.Object.extend('Task');
    const query = new Parse.Query(TaskObject);
    const result = await query.get(taskId);
    return result ? result.toJSON() as Task : undefined;
  },

  addTask: async (task: Task) => {
    const TaskObject = Parse.Object.extend('Task');
    const taskObject = new TaskObject();
    await taskObject.save(task);
  },

  updateTask: async (updatedTask: Task) => {
    const TaskObject = Parse.Object.extend('Task');
    const query = new Parse.Query(TaskObject);
    const taskObject = await query.get(updatedTask.id);
    if (taskObject) {
      await taskObject.save(updatedTask);
    }
  },

  deleteTask: async (taskId: string) => {
    const TaskObject = Parse.Object.extend('Task');
    const query = new Parse.Query(TaskObject);
    const taskObject = await query.get(taskId);
    if (taskObject) {
      await taskObject.destroy();
    }
  },
};


接著我們在App.ts導入並使用。

// App.tsx
import React, { useEffect } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { useColorScheme } from 'react-native';
import Parse from 'parse/react-native';

import HomePage from './src/pages/home.page';
import AddTaskPage from './src/pages/add-task.page';
import StatisticsPage from './src/pages/statistics-page';
import UserPage from './src/pages/user.page';
import LoginPage from './src/pages/login.page';
import SettingsPage from './src/pages/settings.page';
import TaskDetailsPage from './src/pages/task-detail.page';
import { MMKVStorage } from './src/utils/mmkvStorage';

const Tab = createBottomTabNavigator();
const Stack = createNativeStackNavigator();

const PARSE_SERVER_URL = 'http://localhost:1337/parse';
const APP_ID = 'myAppId';
const JAVASCRIPT_KEY = 'myFileKey';

function HomeStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="HomeList" component={HomePage} options={{ title: '任務列表' }} />
      <Stack.Screen name="TaskDetails" component={TaskDetailsPage} options={{ title: '任務詳情' }} />
    </Stack.Navigator>
  );
}

function UserStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen name="UserProfile" component={UserPage} options={{ title: '用戶資料' }} />
      <Stack.Screen name="Settings" component={SettingsPage} options={{ title: '設置' }} />
      <Stack.Screen name="Login" component={LoginPage} options={{ title: '登入' }} />
    </Stack.Navigator>
  );
}

function MainTabs() {
  return (
    <Tab.Navigator>
      <Tab.Screen name="Home" component={HomeStack} options={{ title: '主頁' }} />
      <Tab.Screen name="AddTask" component={AddTaskPage} options={{ title: '新增' }} />
      <Tab.Screen name="Statistics" component={StatisticsPage} options={{ title: '統計' }} />
      <Tab.Screen name="User" component={UserStack} options={{ title: '用戶' }} />
    </Tab.Navigator>
  );
}

function App(): React.JSX.Element {
  const isDarkMode = useColorScheme() === 'dark';
  useEffect(() => {
    // Initialize Parse
    Parse.setAsyncStorage(MMKVStorage);
    Parse.initialize(PARSE_SERVER_URL, APP_ID, JAVASCRIPT_KEY);
  }, []);

  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <SafeAreaProvider>
        <NavigationContainer>
          <MainTabs />
        </NavigationContainer>
      </SafeAreaProvider>
    </GestureHandlerRootView>
  );
}

心得

我們今天簡易的創建了parse service,並且使用該service來讓我們的react native去連接到我們的parse server上,明天我們接續完成。


上一篇
【從零開始學React Native】17. 創建Todo Tracker——建構並架設parse server
下一篇
【從零開始學React Native】19. 創建Todo Tracker——app設置並連接到parse server (中)
系列文
從零開始學React Native20
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言