api-layer

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

API 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

快速参考

PatternWhen
addDoc
Create with auto-ID
setDoc
Create/overwrite with known ID
updateDoc
Partial update
writeBatch
Multiple related writes
ListenersReal-time features
模式使用场景
addDoc
使用自动ID创建文档
setDoc
使用已知ID创建/覆盖文档
updateDoc
部分更新文档
writeBatch
多个关联写入操作
Listeners实时功能