Skip to content

状态管理最佳实践

概述

无论选择哪种状态管理方案,都有一些通用的最佳实践可以帮助构建更加健壮、可维护、高性能的React应用。本文总结了状态管理的通用最佳实践和各种方案的特定实践。

通用设计原则

1. 单一数据源原则

保持数据的唯一来源,避免状态重复:

jsx
// ❌ 错误:多处维护相同数据
const UserProfile = () => {
  const [user, setUser] = useState(null);
  // ...
};

const UserSettings = () => {
  const [user, setUser] = useState(null); // 重复状态
  // ...
};

// ✅ 正确:单一数据源
const userAtom = atom(null);

const UserProfile = () => {
  const user = useAtomValue(userAtom);
  // ...
};

const UserSettings = () => {
  const user = useAtomValue(userAtom); // 共享状态
  // ...
};

// Redux版本
const userSlice = createSlice({
  name: 'user',
  initialState: null,
  reducers: {
    setUser: (state, action) => action.payload
  }
});

// 所有组件都从store获取用户数据
const UserComponent = () => {
  const user = useSelector(state => state.user);
  // ...
};

2. 状态最小化原则

只在全局状态中存储真正需要共享的数据:

jsx
// ❌ 错误:所有状态都放全局
const appState = proxy({
  user: null,
  posts: [],
  
  // 不应该全局化的状态
  currentPage: 1,           // 应该在分页组件内部
  searchInputValue: '',     // 应该在搜索组件内部
  modalOpen: false,         // 应该在模态框组件内部
  tempFormData: {}          // 应该在表单组件内部
});

// ✅ 正确:只存储需要共享的状态
const appState = proxy({
  user: null,        // 多个组件需要
  posts: [],         // 多个组件需要
  theme: 'light'     // 全局主题
});

// 组件内部状态
function SearchComponent() {
  const [query, setQuery] = useState(''); // 仅本组件需要
  const [results, setResults] = useState([]);
  
  // ...
}

function PaginationComponent() {
  const [currentPage, setCurrentPage] = useState(1); // 仅本组件需要
  
  // ...
}

3. 不可变性原则

确保状态更新是不可变的(除非使用Valtio等可变方案):

jsx
// ❌ 错误:直接修改状态
const badReducer = (state, action) => {
  state.count++; // 直接修改
  state.items.push(action.payload); // 直接修改数组
  return state;
};

// ✅ 正确:返回新对象
const goodReducer = (state, action) => {
  return {
    ...state,
    count: state.count + 1,
    items: [...state.items, action.payload]
  };
};

// Redux Toolkit with Immer
const slice = createSlice({
  name: 'example',
  initialState: { count: 0, items: [] },
  reducers: {
    increment: (state) => {
      state.count += 1; // Immer处理不可变性
    },
    addItem: (state, action) => {
      state.items.push(action.payload); // Immer处理不可变性
    }
  }
});

// Zustand with Immer
const useStore = create(
  immer((set) => ({
    count: 0,
    items: [],
    increment: () => set((state) => {
      state.count += 1;
    }),
    addItem: (item) => set((state) => {
      state.items.push(item);
    })
  }))
);

4. 关注点分离原则

将不同类型的状态分离管理:

jsx
// ✅ 按功能域分离
// 用户相关状态
const useAuthStore = create((set) => ({
  user: null,
  token: null,
  login: async (credentials) => {
    const { user, token } = await authAPI.login(credentials);
    set({ user, token });
  },
  logout: () => set({ user: null, token: null })
}));

// UI状态
const useUIStore = create((set) => ({
  theme: 'light',
  sidebarOpen: false,
  notifications: [],
  setTheme: (theme) => set({ theme }),
  toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
  addNotification: (notification) => set((state) => ({
    notifications: [...state.notifications, notification]
  }))
}));

// 业务数据状态
const useDataStore = create((set) => ({
  products: [],
  orders: [],
  cart: [],
  
  fetchProducts: async () => {
    const products = await productsAPI.getAll();
    set({ products });
  }
}));

// Jotai版本 - 原子化分离
const userAtom = atom(null);
const themeAtom = atom('light');
const productsAtom = atom([]);
const cartAtom = atom([]);

性能最佳实践

1. 避免不必要的重渲染

jsx
// ❌ 错误:选择整个状态对象
function BadComponent() {
  const state = useStore(); // 任何状态变化都会重渲染
  return <div>{state.user.name}</div>;
}

// ✅ 正确:精确选择需要的数据
function GoodComponent() {
  const userName = useStore((state) => state.user.name);
  return <div>{userName}</div>;
}

// Context优化
const UserContext = createContext();
const UIContext = createContext();

// 拆分Context避免无关更新
function App() {
  return (
    <UserProvider>
      <UIProvider>
        <MainApp />
      </UIProvider>
    </UserProvider>
  );
}

// 使用React.memo优化
const ExpensiveComponent = React.memo(({ data }) => {
  return <ComplexVisualization data={data} />;
});

// Valtio自动优化
function ValtioComponent() {
  const snap = useSnapshot(state);
  // 只有使用的字段变化才会重渲染
  return <div>{snap.user.name}</div>;
}

2. 合理使用缓存

jsx
// 使用useMemo缓存计算结果
function DataVisualization() {
  const rawData = useStore((state) => state.data);
  const filters = useStore((state) => state.filters);

  const processedData = useMemo(() => {
    return expensiveDataProcessing(rawData, filters);
  }, [rawData, filters]);

  return <Chart data={processedData} />;
}

// Jotai中使用派生atoms
const rawDataAtom = atom([]);
const filtersAtom = atom({});

const processedDataAtom = atom((get) => {
  const rawData = get(rawDataAtom);
  const filters = get(filtersAtom);
  return expensiveDataProcessing(rawData, filters); // 自动缓存
});

// Redux使用Reselect
import { createSelector } from '@reduxjs/toolkit';

const selectRawData = (state) => state.data.raw;
const selectFilters = (state) => state.filters;

const selectProcessedData = createSelector(
  [selectRawData, selectFilters],
  (rawData, filters) => expensiveDataProcessing(rawData, filters)
);

3. 异步操作优化

jsx
// 批量异步操作
async function batchFetchUserData(userIds) {
  const requests = userIds.map(id => fetch(`/api/users/${id}`));
  const responses = await Promise.all(requests);
  const users = await Promise.all(responses.map(r => r.json()));
  
  // 批量更新状态
  setUsers(users);
}

// 使用React Query优化数据获取
function useOptimizedUserData(userId) {
  return useQuery({
    queryKey: ['user', userId],
    queryFn: () => fetchUser(userId),
    staleTime: 5 * 60 * 1000, // 5分钟内不重新获取
    cacheTime: 10 * 60 * 1000, // 缓存10分钟
    refetchOnWindowFocus: false
  });
}

// 预加载策略
function useDataPrefetching() {
  const queryClient = useQueryClient();

  const prefetchUserData = (userId) => {
    queryClient.prefetchQuery({
      queryKey: ['user', userId],
      queryFn: () => fetchUser(userId)
    });
  };

  return { prefetchUserData };
}

// Jotai异步atoms
const userFamily = atomFamily({
  key: 'user',
  default: async (userId) => {
    const response = await fetch(`/api/users/${userId}`);
    return response.json();
  }
});

// 条件性异步调用
const conditionalDataAtom = atom(async (get) => {
  const shouldFetch = get(shouldFetchDataAtom);
  if (!shouldFetch) return null;
  
  const response = await fetch('/api/data');
  return response.json();
});

架构最佳实践

1. 分层架构

jsx
// 三层架构:Presentation -> Business -> Data
// 数据层 (Data Layer)
class UserService {
  async getUsers() {
    const response = await fetch('/api/users');
    return response.json();
  }

  async createUser(userData) {
    const response = await fetch('/api/users', {
      method: 'POST',
      body: JSON.stringify(userData)
    });
    return response.json();
  }
}

// 业务逻辑层 (Business Layer)
const useUserBusiness = () => {
  const userService = useUserService();
  const setUsers = useSetAtom(usersAtom);
  const setLoading = useSetAtom(loadingAtom);

  const loadUsers = async () => {
    setLoading(true);
    try {
      const users = await userService.getUsers();
      setUsers(users);
    } catch (error) {
      console.error('Failed to load users:', error);
    } finally {
      setLoading(false);
    }
  };

  const createUser = async (userData) => {
    try {
      const newUser = await userService.createUser(userData);
      setUsers(prev => [...prev, newUser]);
      return newUser;
    } catch (error) {
      throw new Error('Failed to create user');
    }
  };

  return { loadUsers, createUser };
};

// 表现层 (Presentation Layer)
function UserList() {
  const users = useAtomValue(usersAtom);
  const loading = useAtomValue(loadingAtom);
  const { loadUsers, createUser } = useUserBusiness();

  useEffect(() => {
    loadUsers();
  }, []);

  if (loading) return <LoadingSpinner />;

  return (
    <div>
      {users.map(user => (
        <UserCard key={user.id} user={user} />
      ))}
      <CreateUserForm onCreate={createUser} />
    </div>
  );
}

2. 状态标准化

jsx
// ❌ 错误:嵌套的非标准化数据
const badState = {
  posts: [
    {
      id: 1,
      title: 'Post 1',
      author: { id: 1, name: 'Alice', email: 'alice@example.com' },
      comments: [
        { id: 1, text: 'Comment 1', author: { id: 2, name: 'Bob' } },
        { id: 2, text: 'Comment 2', author: { id: 1, name: 'Alice', email: 'alice@example.com' } }
      ]
    }
  ]
};

// ✅ 正确:标准化的扁平结构
const goodState = {
  entities: {
    users: {
      1: { id: 1, name: 'Alice', email: 'alice@example.com' },
      2: { id: 2, name: 'Bob', email: 'bob@example.com' }
    },
    posts: {
      1: { id: 1, title: 'Post 1', authorId: 1, commentIds: [1, 2] }
    },
    comments: {
      1: { id: 1, text: 'Comment 1', authorId: 2, postId: 1 },
      2: { id: 2, text: 'Comment 2', authorId: 1, postId: 1 }
    }
  },
  ui: {
    selectedPostId: null,
    loading: false
  }
};

// Redux Toolkit Entity Adapter
const usersAdapter = createEntityAdapter();
const postsAdapter = createEntityAdapter();
const commentsAdapter = createEntityAdapter();

const usersSlice = createSlice({
  name: 'users',
  initialState: usersAdapter.getInitialState(),
  reducers: {
    userAdded: usersAdapter.addOne,
    userUpdated: usersAdapter.updateOne,
    usersLoaded: usersAdapter.setAll
  }
});

// Jotai版本
const usersAtom = atom({});
const postsAtom = atom({});
const commentsAtom = atom({});

// 辅助selectors
const userByIdFamily = atomFamily({
  key: 'userById',
  default: (userId) => atom((get) => get(usersAtom)[userId])
});

const postWithDetailsFamily = atomFamily({
  key: 'postWithDetails',
  default: (postId) => atom((get) => {
    const posts = get(postsAtom);
    const users = get(usersAtom);
    const comments = get(commentsAtom);
    
    const post = posts[postId];
    if (!post) return null;
    
    return {
      ...post,
      author: users[post.authorId],
      comments: post.commentIds.map(id => ({
        ...comments[id],
        author: users[comments[id].authorId]
      }))
    };
  })
});

3. 关注点分离

jsx
// 按功能领域分离状态管理逻辑

// auth/authStore.js - 认证相关
export const useAuthStore = create((set) => ({
  user: null,
  token: null,
  login: async (credentials) => {
    const response = await authAPI.login(credentials);
    set({ user: response.user, token: response.token });
  },
  logout: () => set({ user: null, token: null })
}));

// products/productsStore.js - 产品相关
export const useProductsStore = create((set) => ({
  products: [],
  selectedProduct: null,
  filters: {},
  
  fetchProducts: async () => {
    const products = await productsAPI.getAll();
    set({ products });
  },
  
  setFilters: (filters) => set({ filters }),
  selectProduct: (product) => set({ selectedProduct: product })
}));

// ui/uiStore.js - UI状态
export const useUIStore = create((set) => ({
  theme: 'light',
  sidebarOpen: false,
  notifications: [],
  
  setTheme: (theme) => set({ theme }),
  toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
  
  addNotification: (notification) => set((state) => ({
    notifications: [...state.notifications, {
      id: Date.now(),
      ...notification,
      timestamp: new Date().toISOString()
    }]
  })),
  
  removeNotification: (id) => set((state) => ({
    notifications: state.notifications.filter(n => n.id !== id)
  }))
}));

数据流最佳实践

1. 单向数据流

jsx
// 保持清晰的数据流向:UI事件 -> Actions -> State -> UI更新

// ❌ 错误:组件直接修改全局状态
function BadComponent() {
  const { data, setData } = useStore();
  
  // 直接在组件中修改复杂逻辑
  const handleComplexOperation = () => {
    // 复杂的业务逻辑混在组件中
    const processed = complexProcessing(data);
    setData(processed);
    updateOtherData(processed);
    triggerSideEffects();
  };

  return <button onClick={handleComplexOperation}>Process</button>;
}

// ✅ 正确:通过actions处理业务逻辑
function GoodComponent() {
  const data = useStore((state) => state.data);
  const processData = useStore((state) => state.processData);

  return <button onClick={processData}>Process</button>;
}

const useStore = create((set, get) => ({
  data: [],
  
  processData: async () => {
    const currentData = get().data;
    
    // 业务逻辑封装在store中
    const processed = await complexProcessing(currentData);
    
    set({ data: processed });
    
    // 相关的副作用
    await updateOtherSystems(processed);
    triggerAnalytics('data_processed');
  }
}));

2. 异步操作标准化

jsx
// 标准化的异步操作模式
const createAsyncSlice = (name, apiCall) => {
  return createSlice({
    name,
    initialState: {
      data: null,
      loading: false,
      error: null,
      lastFetch: null
    },
    reducers: {},
    extraReducers: (builder) => {
      const asyncThunk = createAsyncThunk(
        `${name}/fetch`,
        apiCall
      );

      builder
        .addCase(asyncThunk.pending, (state) => {
          state.loading = true;
          state.error = null;
        })
        .addCase(asyncThunk.fulfilled, (state, action) => {
          state.loading = false;
          state.data = action.payload;
          state.lastFetch = Date.now();
        })
        .addCase(asyncThunk.rejected, (state, action) => {
          state.loading = false;
          state.error = action.error.message;
        });

      return { ...createSlice, asyncThunk };
    }
  });
};

// 使用
const usersSlice = createAsyncSlice('users', () => 
  fetch('/api/users').then(r => r.json())
);

// Zustand版本
const createAsyncStore = (fetcher) => create((set) => ({
  data: null,
  loading: false,
  error: null,
  
  fetch: async () => {
    set({ loading: true, error: null });
    try {
      const data = await fetcher();
      set({ data, loading: false });
    } catch (error) {
      set({ error: error.message, loading: false });
    }
  }
}));

// Jotai版本
const createAsyncAtom = (key, fetcher) => {
  const dataAtom = atom(async () => {
    return await fetcher();
  });
  
  const loadableAtom = loadable(dataAtom);
  
  return loadableAtom;
};

3. 错误处理标准化

jsx
// 全局错误处理
const errorHandlingStore = create((set) => ({
  errors: [],
  
  addError: (error) => set((state) => ({
    errors: [...state.errors, {
      id: Date.now(),
      message: error.message,
      type: error.type || 'error',
      timestamp: new Date().toISOString(),
      stack: error.stack
    }]
  })),
  
  removeError: (id) => set((state) => ({
    errors: state.errors.filter(e => e.id !== id)
  })),
  
  clearErrors: () => set({ errors: [] })
}));

// 统一的错误处理Hook
function useErrorHandler() {
  const addError = useStore((state) => state.addError);

  const handleAsyncError = (asyncFn) => async (...args) => {
    try {
      return await asyncFn(...args);
    } catch (error) {
      addError({
        message: error.message,
        type: 'api_error',
        context: { fn: asyncFn.name, args }
      });
      throw error;
    }
  };

  return { handleAsyncError };
}

// 使用错误处理
function UserService() {
  const { handleAsyncError } = useErrorHandler();

  const fetchUsers = handleAsyncError(async () => {
    const response = await fetch('/api/users');
    if (!response.ok) throw new Error('Failed to fetch users');
    return response.json();
  });

  return { fetchUsers };
}

代码组织最佳实践

1. 文件结构

src/
├── stores/               # 状态管理
│   ├── auth/
│   │   ├── authStore.js
│   │   ├── authTypes.js
│   │   └── authSelectors.js
│   ├── products/
│   │   ├── productsStore.js
│   │   └── productsSelectors.js
│   └── index.js         # 导出所有stores

├── hooks/               # 自定义hooks
│   ├── useAuth.js
│   ├── useProducts.js
│   └── useAPI.js

├── services/           # API服务
│   ├── authAPI.js
│   ├── productsAPI.js
│   └── baseAPI.js

└── utils/             # 工具函数
    ├── stateUtils.js
    └── validation.js

2. 命名约定

jsx
// Store命名
const useUserStore = create(...);    // use + 领域 + Store
const useProductsStore = create(...);
const useUIStore = create(...);

// Action命名 - 动词开头
const actions = {
  // 数据操作
  fetchUsers: () => {},
  createUser: () => {},
  updateUser: () => {},
  deleteUser: () => {},
  
  // UI操作
  openModal: () => {},
  closeModal: () => {},
  setTheme: () => {},
  toggleSidebar: () => {},
  
  // 业务操作
  processOrder: () => {},
  calculateDiscount: () => {},
  validateForm: () => {}
};

// Atom命名
const userAtom = atom(null);           // 数据atom
const isLoadingAtom = atom(false);     // 状态atom
const userFormAtom = atom({});         // 表单atom

// Selector命名
const filteredUsersAtom = atom((get) => {}); // 派生atom
const userStatsAtom = atom((get) => {});     // 计算atom

3. 类型定义

typescript
// 集中的类型定义
// types/index.ts
export interface User {
  id: number;
  name: string;
  email: string;
  role: 'admin' | 'user';
  createdAt: string;
}

export interface Product {
  id: number;
  name: string;
  price: number;
  category: string;
  inStock: boolean;
}

export interface CartItem {
  id: string;
  productId: number;
  quantity: number;
  options: Record<string, any>;
}

// Store类型
export interface UserStore {
  users: User[];
  currentUser: User | null;
  loading: boolean;
  error: string | null;
  
  fetchUsers: () => Promise<void>;
  setCurrentUser: (user: User) => void;
  updateUser: (id: number, updates: Partial<User>) => void;
}

// 使用泛型创建可复用的store类型
export interface AsyncState<T> {
  data: T | null;
  loading: boolean;
  error: string | null;
  lastFetch: number | null;
}

export interface EntityStore<T> extends AsyncState<T[]> {
  selectedId: number | null;
  filters: Record<string, any>;
}

测试最佳实践

1. Store测试

jsx
// Zustand store测试
import { act, renderHook } from '@testing-library/react';

describe('useUserStore', () => {
  beforeEach(() => {
    useUserStore.setState({ users: [], loading: false, error: null });
  });

  it('should add user', () => {
    const { result } = renderHook(() => useUserStore());
    
    act(() => {
      result.current.addUser({ id: 1, name: 'John' });
    });

    expect(result.current.users).toHaveLength(1);
    expect(result.current.users[0].name).toBe('John');
  });

  it('should handle async operations', async () => {
    // Mock API
    jest.spyOn(userAPI, 'fetchUsers').mockResolvedValue([
      { id: 1, name: 'John' }
    ]);

    const { result } = renderHook(() => useUserStore());

    await act(async () => {
      await result.current.fetchUsers();
    });

    expect(result.current.users).toHaveLength(1);
    expect(result.current.loading).toBe(false);
  });
});

// Jotai atoms测试
describe('userAtom', () => {
  it('should store user data', () => {
    const { result } = renderHook(() => useAtom(userAtom));
    
    act(() => {
      result.current[1]({ id: 1, name: 'John' });
    });

    expect(result.current[0]).toEqual({ id: 1, name: 'John' });
  });
});

// Redux slice测试
describe('userSlice', () => {
  it('should handle user creation', () => {
    const initialState = { users: [] };
    const action = { type: 'users/userAdded', payload: { id: 1, name: 'John' } };
    
    const newState = userSlice.reducer(initialState, action);
    
    expect(newState.users).toHaveLength(1);
  });
});

2. 组件集成测试

jsx
// 测试组件与状态的集成
import { render, screen, fireEvent } from '@testing-library/react';
import { RecoilRoot } from 'recoil';

function TestWrapper({ children }) {
  return (
    <RecoilRoot>
      {children}
    </RecoilRoot>
  );
}

describe('UserList component', () => {
  it('should display users from store', () => {
    const { result } = renderHook(() => useUserStore());
    
    act(() => {
      result.current.addUser({ id: 1, name: 'John' });
    });

    render(<UserList />, { wrapper: TestWrapper });

    expect(screen.getByText('John')).toBeInTheDocument();
  });

  it('should handle user interaction', () => {
    render(<UserList />, { wrapper: TestWrapper });
    
    const addButton = screen.getByRole('button', { name: 'Add User' });
    fireEvent.click(addButton);
    
    // 验证状态变化
    expect(screen.getByText('User added')).toBeInTheDocument();
  });
});

性能监控和调试

1. 性能监控

jsx
// 性能监控Hook
function usePerformanceMonitor(componentName) {
  const renderCount = useRef(0);
  const startTime = useRef(performance.now());

  useEffect(() => {
    renderCount.current++;
    const endTime = performance.now();
    
    console.log(`[${componentName}] Render #${renderCount.current}, Duration: ${endTime - startTime.current}ms`);
    
    startTime.current = endTime;
  });
}

// 状态变化监控
const useStateChangeMonitor = (store, storeName) => {
  useEffect(() => {
    const unsubscribe = store.subscribe((state, prevState) => {
      const changes = {};
      Object.keys(state).forEach(key => {
        if (state[key] !== prevState[key]) {
          changes[key] = { from: prevState[key], to: state[key] };
        }
      });
      
      if (Object.keys(changes).length > 0) {
        console.log(`[${storeName}] State changes:`, changes);
      }
    });

    return unsubscribe;
  }, []);
};

// 使用
function MonitoredComponent() {
  usePerformanceMonitor('UserList');
  useStateChangeMonitor(useUserStore, 'UserStore');
  
  // 组件逻辑
}

2. 调试工具

jsx
// 开发环境调试助手
const createDebugStore = (storeCreator, name) => {
  if (process.env.NODE_ENV === 'development') {
    return create(
      devtools(
        subscribeWithSelector(storeCreator),
        { name }
      )
    );
  }
  
  return create(storeCreator);
};

// 状态快照工具
const createStateSnapshot = () => {
  const stores = {
    user: useUserStore.getState(),
    products: useProductsStore.getState(),
    ui: useUIStore.getState()
  };
  
  return {
    timestamp: new Date().toISOString(),
    stores,
    
    export: () => JSON.stringify(stores, null, 2),
    
    import: (snapshotJson) => {
      const snapshot = JSON.parse(snapshotJson);
      useUserStore.setState(snapshot.user);
      useProductsStore.setState(snapshot.products);
      useUIStore.setState(snapshot.ui);
    }
  };
};

// 使用
function DebugPanel() {
  const [snapshot, setSnapshot] = useState(null);

  const handleExport = () => {
    const snap = createStateSnapshot();
    setSnapshot(snap);
    console.log('State exported:', snap.export());
  };

  return (
    <div>
      <button onClick={handleExport}>Export State</button>
      {snapshot && (
        <textarea value={snapshot.export()} readOnly />
      )}
    </div>
  );
}

安全最佳实践

1. 敏感数据处理

jsx
// ❌ 错误:敏感数据直接存储在状态中
const badAuthStore = create((set) => ({
  user: null,
  password: '', // 不应该存储密码
  creditCard: '', // 不应该存储信用卡信息
  socialSecurityNumber: '' // 不应该存储敏感信息
}));

// ✅ 正确:只存储必要的用户信息
const goodAuthStore = create((set) => ({
  user: {
    id: null,
    email: null,
    name: null,
    role: null,
    // 不存储敏感信息
  },
  token: null, // JWT token(应该设置过期时间)
  
  // 登录时不存储密码
  login: async (email, password) => {
    const response = await authAPI.login(email, password);
    // password 不会被存储
    set({ 
      user: response.user, 
      token: response.token 
    });
  }
}));

// 敏感操作的处理
const secureOperations = {
  // 支付操作:不存储支付信息
  processPayment: async (paymentDetails) => {
    // 直接传递给支付服务,不存储在状态中
    return await paymentService.process(paymentDetails);
  },
  
  // 敏感信息更新:立即清除
  updateSensitiveInfo: async (info) => {
    try {
      await userAPI.updateSensitive(info);
      // 成功后立即清除本地引用
      info = null;
    } catch (error) {
      // 错误时也要清除
      info = null;
      throw error;
    }
  }
};

2. 输入验证和清理

jsx
// 输入验证中间件
const validationMiddleware = (config) => (set, get, api) => {
  return config(
    (partial, replace, action) => {
      // 验证输入数据
      if (typeof partial === 'object' && partial !== null) {
        const validatedData = validateAndSanitize(partial);
        set(validatedData, replace, action);
      } else {
        set(partial, replace, action);
      }
    },
    get,
    api
  );
};

function validateAndSanitize(data) {
  const sanitized = {};
  
  Object.entries(data).forEach(([key, value]) => {
    if (typeof value === 'string') {
      // XSS防护:清理HTML标签
      sanitized[key] = value.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi, '');
    } else {
      sanitized[key] = value;
    }
  });
  
  return sanitized;
}

// 使用验证中间件
const useSecureStore = create(
  validationMiddleware((set) => ({
    userInput: '',
    setUserInput: (input) => set({ userInput: input })
  }))
);

可维护性最佳实践

1. 文档和注释

jsx
/**
 * 用户认证Store
 * 管理用户登录状态、个人信息和权限
 * 
 * @example
 * const { user, login, logout } = useAuthStore();
 * 
 * if (user) {
 *   // 用户已登录
 * }
 */
const useAuthStore = create((set, get) => ({
  /**
   * 当前登录用户信息
   * @type {User | null}
   */
  user: null,

  /**
   * 认证token
   * @type {string | null}
   */
  token: null,

  /**
   * 用户登录
   * @param {Object} credentials - 登录凭据
   * @param {string} credentials.email - 邮箱
   * @param {string} credentials.password - 密码
   * @returns {Promise<User>} 返回用户信息
   * @throws {Error} 登录失败时抛出错误
   */
  login: async (credentials) => {
    const response = await authAPI.login(credentials);
    set({ user: response.user, token: response.token });
    return response.user;
  },

  /**
   * 用户登出
   * 清除用户信息和token,并通知服务器
   * @returns {Promise<void>}
   */
  logout: async () => {
    await authAPI.logout();
    set({ user: null, token: null });
  },

  /**
   * 检查用户是否有特定权限
   * @param {string} permission - 权限名称
   * @returns {boolean} 是否有权限
   */
  hasPermission: (permission) => {
    const { user } = get();
    return user?.permissions?.includes(permission) || false;
  }
}));

2. 代码复用

jsx
// 创建可复用的store模式
function createCRUDStore(entityName, apiService) {
  return create((set, get) => ({
    // 标准CRUD状态
    items: [],
    selectedItem: null,
    loading: false,
    error: null,
    
    // 标准CRUD操作
    fetchItems: async () => {
      set({ loading: true, error: null });
      try {
        const items = await apiService.getAll();
        set({ items, loading: false });
      } catch (error) {
        set({ error: error.message, loading: false });
      }
    },
    
    createItem: async (itemData) => {
      const newItem = await apiService.create(itemData);
      set((state) => ({ 
        items: [...state.items, newItem] 
      }));
      return newItem;
    },
    
    updateItem: async (id, updates) => {
      const updatedItem = await apiService.update(id, updates);
      set((state) => ({
        items: state.items.map(item => 
          item.id === id ? updatedItem : item
        )
      }));
      return updatedItem;
    },
    
    deleteItem: async (id) => {
      await apiService.delete(id);
      set((state) => ({
        items: state.items.filter(item => item.id !== id),
        selectedItem: state.selectedItem?.id === id ? null : state.selectedItem
      }));
    },
    
    selectItem: (item) => set({ selectedItem: item }),
    
    clearSelection: () => set({ selectedItem: null })
  }));
}

// 使用
const useUsersStore = createCRUDStore('user', userAPI);
const useProductsStore = createCRUDStore('product', productAPI);
const useOrdersStore = createCRUDStore('order', orderAPI);

3. 配置和环境管理

jsx
// 环境相关的store配置
const createStoreWithConfig = (storeCreator) => {
  const isDevelopment = process.env.NODE_ENV === 'development';
  const enableDevtools = isDevelopment && window.__REDUX_DEVTOOLS_EXTENSION__;
  
  let store = storeCreator;
  
  // 开发环境增强
  if (isDevelopment) {
    if (enableDevtools) {
      store = devtools(store, { name: 'AppStore' });
    }
    
    // 添加日志
    store = subscribeWithSelector(store);
    
    // 性能监控
    store = (...args) => {
      const result = storeCreator(...args);
      
      // 监控状态变化
      result.subscribe((state, prevState) => {
        console.group('State Change');
        console.log('Previous:', prevState);
        console.log('Current:', state);
        console.groupEnd();
      });
      
      return result;
    };
  }
  
  return create(store);
};

// 配置驱动的store
const config = {
  enablePersistence: true,
  enableDevtools: process.env.NODE_ENV === 'development',
  enableAnalytics: process.env.NODE_ENV === 'production',
  cacheTimeout: 5 * 60 * 1000 // 5分钟
};

const useConfigurableStore = create(
  config.enablePersistence
    ? persist(storeCreator, { name: 'app-store' })
    : storeCreator
);

团队协作最佳实践

1. 代码审查标准

jsx
// 状态管理代码审查清单
const codeReviewChecklist = [
  // 设计层面
  '□ 状态结构合理,避免深度嵌套',
  '□ 遵循单一数据源原则',
  '□ 状态最小化,只存储必要信息',
  '□ 关注点正确分离',
  
  // 实现层面
  '□ 使用不可变更新(除Valtio外)',
  '□ 异步操作正确处理loading/error状态',
  '□ Actions命名清晰描述其作用',
  '□ 适当使用缓存和性能优化',
  
  // 质量层面
  '□ 添加必要的注释和文档',
  '□ 类型定义完整(TypeScript项目)',
  '□ 错误处理完善',
  '□ 测试覆盖关键逻辑',
  
  // 安全层面
  '□ 不存储敏感信息在状态中',
  '□ 输入验证和清理',
  '□ 权限检查到位'
];

2. 团队规范

jsx
// 团队开发规范示例
const teamGuidelines = {
  // Store命名
  naming: {
    stores: 'use + 功能域 + Store (如: useUserStore)',
    atoms: '功能 + Atom (如: userAtom)',
    selectors: '描述性名称 + Selector (如: filteredUsersSelector)',
    actions: '动词开头 (如: fetchUsers, updateUser)'
  },
  
  // 文件组织
  structure: {
    smallProject: 'stores/index.js - 所有stores在一个文件',
    mediumProject: 'stores/按功能域分文件',
    largeProject: 'features/各功能模块包含自己的状态'
  },
  
  // 状态设计
  stateDesign: [
    '优先使用原生类型而不是复杂对象',
    '避免在状态中存储派生数据',
    '合理拆分状态粒度',
    '考虑状态的生命周期'
  ],
  
  // 性能要求
  performance: [
    '使用精确的selectors避免不必要渲染',
    '大量数据使用虚拟化',
    '合理使用React.memo',
    '避免在render中创建对象/函数'
  ]
};

// 团队培训材料
const trainingMaterials = {
  // 新员工培训
  onboarding: [
    '状态管理基础概念',
    '项目使用的具体方案',
    '团队代码规范',
    '调试工具使用',
    '常见问题和解决方案'
  ],
  
  // 进阶培训
  advanced: [
    '性能优化技巧',
    '复杂状态设计模式',
    '测试策略',
    '架构设计原则'
  ]
};

3. 版本控制和迁移

jsx
// 状态schema版本控制
const stateVersioning = {
  version: '1.2.0',
  
  migrations: {
    '1.0.0': (oldState) => oldState,
    
    '1.1.0': (oldState) => ({
      ...oldState,
      user: {
        ...oldState.user,
        preferences: oldState.user.settings // 重命名字段
      }
    }),
    
    '1.2.0': (oldState) => ({
      ...oldState,
      ui: {
        ...oldState.ui,
        theme: oldState.ui.darkMode ? 'dark' : 'light' // 重构主题系统
      }
    })
  },
  
  migrate: (persistedState, currentVersion) => {
    let state = persistedState;
    
    Object.keys(migrations).forEach(version => {
      if (compareVersions(version, persistedState.version) > 0 &&
          compareVersions(version, currentVersion) <= 0) {
        state = migrations[version](state);
      }
    });
    
    return { ...state, version: currentVersion };
  }
};

// 在persist中间件中使用
const useVersionedStore = create(
  persist(
    storeCreator,
    {
      name: 'app-store',
      version: stateVersioning.version,
      migrate: stateVersioning.migrate
    }
  )
);

总结

状态管理最佳实践的核心原则:

设计原则

  1. 单一数据源:避免状态重复
  2. 状态最小化:只存储必要的全局状态
  3. 不可变性:确保状态更新的可预测性
  4. 关注点分离:按功能域组织状态

性能原则

  1. 精确订阅:避免不必要的重渲染
  2. 合理缓存:使用memo缓存计算结果
  3. 异步优化:标准化异步操作模式
  4. 监控调试:建立性能监控机制

质量原则

  1. 类型安全:使用TypeScript确保类型正确
  2. 错误处理:建立统一的错误处理机制
  3. 测试覆盖:为状态逻辑编写测试
  4. 文档完善:为复杂逻辑添加文档

团队原则

  1. 规范统一:建立团队代码标准
  2. 知识分享:定期技术分享和review
  3. 渐进迁移:制定合理的技术迁移计划
  4. 持续改进:定期评估和优化状态管理方案

遵循这些最佳实践,无论使用哪种状态管理库,都能构建出高质量的React应用。