api-layer
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseAPI Layer Patterns
API层模式
File Location
文件位置
All API functions go in :
[feature]/api/src/
├── post/
│ └── api/
│ ├── post.ts # CRUD operations
│ └── postQueries.ts # React Query hooks所有API函数都放在目录下:
[feature]/api/src/
├── post/
│ └── api/
│ ├── post.ts # CRUD操作
│ └── postQueries.ts # React Query钩子Function Structure
函数结构
typescript
import { collection, addDoc, query, where, getDocs } from 'firebase/firestore';
import { db } from '@/firebase';
import type { Post } from '../model/Post';
export async function createPost(
boardId: string,
postData: Omit<Post, 'id' | 'createdAt'>,
): Promise<Post> {
const postsRef = collection(db, 'boards', boardId, 'posts');
const docRef = await addDoc(postsRef, {
...postData,
createdAt: new Date(),
});
return { ...postData, id: docRef.id, createdAt: new Date() };
}typescript
import { collection, addDoc, query, where, getDocs } from 'firebase/firestore';
import { db } from '@/firebase';
import type { Post } from '../model/Post';
export async function createPost(
boardId: string,
postData: Omit<Post, 'id' | 'createdAt'>,
): Promise<Post> {
const postsRef = collection(db, 'boards', boardId, 'posts');
const docRef = await addDoc(postsRef, {
...postData,
createdAt: new Date(),
});
return { ...postData, id: docRef.id, createdAt: new Date() };
}Firestore Best Practices
Firestore最佳实践
Batch Writes for Related Operations
关联操作的批量写入
typescript
import { writeBatch, doc } from 'firebase/firestore';
const batch = writeBatch(db);
batch.set(doc(db, 'posts', postId), postData);
batch.update(doc(db, 'users', userId), { postCount: increment(1) });
await batch.commit();typescript
import { writeBatch, doc } from 'firebase/firestore';
const batch = writeBatch(db);
batch.set(doc(db, 'posts', postId), postData);
batch.update(doc(db, 'users', userId), { postCount: increment(1) });
await batch.commit();Collection Paths
集合路径
users/{userId}
users/{userId}/postings/{postingId}
users/{userId}/commentings/{commentingId}
boards/{boardId}/posts/{postId}
boards/{boardId}/posts/{postId}/comments/{commentId}
boards/{boardId}/posts/{postId}/comments/{commentId}/replies/{replyId}users/{userId}
users/{userId}/postings/{postingId}
users/{userId}/commentings/{commentingId}
boards/{boardId}/posts/{postId}
boards/{boardId}/posts/{postId}/comments/{commentId}
boards/{boardId}/posts/{postId}/comments/{commentId}/replies/{replyId}Optimistic Updates with React Query
使用React Query进行乐观更新
typescript
const mutation = useMutation({
mutationFn: createPost,
onMutate: async (newPost) => {
await queryClient.cancelQueries({ queryKey: ['posts'] });
const previous = queryClient.getQueryData(['posts']);
queryClient.setQueryData(['posts'], (old) => [...old, newPost]);
return { previous };
},
onError: (err, newPost, context) => {
queryClient.setQueryData(['posts'], context.previous);
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['posts'] });
},
});typescript
const mutation = useMutation({
mutationFn: createPost,
onMutate: async (newPost) => {
await queryClient.cancelQueries({ queryKey: ['posts'] });
const previous = queryClient.getQueryData(['posts']);
queryClient.setQueryData(['posts'], (old) => [...old, newPost]);
return { previous };
},
onError: (err, newPost, context) => {
queryClient.setQueryData(['posts'], context.previous);
},
onSettled: () => {
queryClient.invalidateQueries({ queryKey: ['posts'] });
},
});Quick Reference
快速参考
| Pattern | When |
|---|---|
| Create with auto-ID |
| Create/overwrite with known ID |
| Partial update |
| Multiple related writes |
| Listeners | Real-time features |
| 模式 | 使用场景 |
|---|---|
| 使用自动ID创建文档 |
| 使用已知ID创建/覆盖文档 |
| 部分更新文档 |
| 多个关联写入操作 |
| Listeners | 实时功能 |