今天我們開始在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上,明天我們接續完成。