// 这是我在真实项目中看到的代码模式 function ComplexDataDashboard({ projectId, userId }) { const [projectData, setProjectData] = useState(null); const [userData, setUserData] = useState(null); const [permissions, setPermissions] = useState([]); const [analytics, setAnalytics] = useState(null); const [notifications, setNotifications] = useState([]); const [isLoading, setIsLoading] = useState(false); const [loadingSteps, setLoadingSteps] = useState(0); const [error, setError] = useState(null); const [retryCount, setRetryCount] = useState(0); // 加载项目数据 useEffect(() => { setIsLoading(true); setError(null); fetchProjectData(projectId) .then(data => { setProjectData(data); setLoadingSteps(prev => prev + 1); }) .catch(err => { setError(err); setIsLoading(false); }); }, [projectId, retryCount]); // 加载用户数据 useEffect(() => { if (projectData) { fetchUserData(userId) .then(data => { setUserData(data); setLoadingSteps(prev => prev + 1); }); } }, [userId, projectData]); // 加载权限信息 useEffect(() => { if (userData && projectData) { fetchUserPermissions(userId, projectData.id) .then(perms => { setPermissions(perms); setLoadingSteps(prev => prev + 1); }); } }, [userData, projectData, userId]); // 加载分析数据 useEffect(() => { if (permissions.length > 0 && permissions.includes('view_analytics')) { fetchAnalytics(projectId) .then(data => { setAnalytics(data); setLoadingSteps(prev => prev + 1); }); } }, [permissions, projectId]); // 加载通知 useEffect(() => { if (userData) { fetchNotifications(userId) .then(notifs => { setNotifications(notifs); setLoadingSteps(prev => prev + 1); }); } }, [userData, userId]); // 检查是否全部加载完成 useEffect(() => { const expectedSteps = permissions.includes('view_analytics') ? 5 : 4; if (loadingSteps >= expectedSteps) { setIsLoading(false); } }, [loadingSteps, permissions]); // 堆代码 duidaima.com // 重试逻辑 useEffect(() => { if (error && retryCount < 3) { const timer = setTimeout(() => { setRetryCount(prev => prev + 1); }, 2000 * Math.pow(2, retryCount)); return() => clearTimeout(timer); } }, [error, retryCount]); }这种模式的问题分析
优化策略一:状态聚合与原子化更新
// 定义完整的状态结构和action类型 const initialState = { // 数据状态 projectData: null, userData: null, permissions: [], analytics: null, notifications: [], // 加载状态 loading: { project: false, user: false, permissions: false, analytics: false, notifications: false }, // 全局状态 isInitialized: false, error: null, retryCount: 0 }; function dashboardReducer(state, action) { switch (action.type) { case'INIT_LOADING': return { ...state, loading: { ...state.loading, project: true }, error: null, isInitialized: false }; case'PROJECT_LOADED': return { ...state, projectData: action.payload, loading: { ...state.loading, project: false, user: true } }; case'USER_LOADED': return { ...state, userData: action.payload, loading: { ...state.loading, user: false, permissions: true, notifications: true } }; case'PERMISSIONS_LOADED': const hasAnalyticsPermission = action.payload.includes('view_analytics'); return { ...state, permissions: action.payload, loading: { ...state.loading, permissions: false, analytics: hasAnalyticsPermission } }; case'ANALYTICS_LOADED': return { ...state, analytics: action.payload, loading: { ...state.loading, analytics: false } }; case'NOTIFICATIONS_LOADED': return { ...state, notifications: action.payload, loading: { ...state.loading, notifications: false } }; case'ALL_LOADED': return { ...state, isInitialized: true }; case'SET_ERROR': return { ...state, error: action.payload, loading: initialState.loading }; case'RETRY': return { ...state, retryCount: state.retryCount + 1, error: null }; default: return state; } } // 重构后的组件 function OptimizedDashboard({ projectId, userId }) { const [state, dispatch] = useReducer(dashboardReducer, initialState); // 核心数据加载逻辑 - 只需要一个useEffect useEffect(() => { asyncfunction loadDashboardData() { try { dispatch({ type: 'INIT_LOADING' }); // Step 1: 加载项目数据 const projectData = await fetchProjectData(projectId); dispatch({ type: 'PROJECT_LOADED', payload: projectData }); // Step 2: 并行加载用户数据 const userData = await fetchUserData(userId); dispatch({ type: 'USER_LOADED', payload: userData }); // Step 3: 加载权限和通知(可并行) const [permissions, notifications] = awaitPromise.all([ fetchUserPermissions(userId, projectData.id), fetchNotifications(userId) ]); dispatch({ type: 'PERMISSIONS_LOADED', payload: permissions }); dispatch({ type: 'NOTIFICATIONS_LOADED', payload: notifications }); // Step 4: 根据权限决定是否加载分析数据 if (permissions.includes('view_analytics')) { const analytics = await fetchAnalytics(projectId); dispatch({ type: 'ANALYTICS_LOADED', payload: analytics }); } dispatch({ type: 'ALL_LOADED' }); } catch (error) { dispatch({ type: 'SET_ERROR', payload: error }); } } loadDashboardData(); }, [projectId, userId, state.retryCount]); // 自动重试逻辑 useEffect(() => { if (state.error && state.retryCount < 3) { const timer = setTimeout(() => { dispatch({ type: 'RETRY' }); }, 2000 * Math.pow(2, state.retryCount)); return() => clearTimeout(timer); } }, [state.error, state.retryCount]); return ( <div> {state.isInitialized ? ( <DashboardContent {...state} /> ) : ( <LoadingIndicator loading={state.loading} /> )} </div> ); }性能提升分析
渲染减少:约65%
内存减少:约40%
// 高级数据获取Hook function useDashboardData(projectId, userId, options = {}) { const { enableRetry = true, maxRetries = 3, retryDelay = 2000, enableCache = true } = options; const [state, setState] = useState({ data: { project: null, user: null, permissions: [], analytics: null, notifications: [] }, meta: { isLoading: false, isInitialized: false, loadingProgress: 0, error: null, retryCount: 0, lastUpdated: null } }); // 缓存机制 const cacheKey = useMemo(() =>`${projectId}-${userId}`, [projectId, userId]); const cache = useRef(newMap()); // 数据加载函数 const loadData = useCallback(async () => { // 检查缓存 if (enableCache && cache.current.has(cacheKey)) { const cachedData = cache.current.get(cacheKey); const cacheAge = Date.now() - cachedData.timestamp; if (cacheAge < 300000) { // 5分钟缓存 setState(prev => ({ data: cachedData.data, meta: { ...prev.meta, isLoading: false, isInitialized: true, loadingProgress: 100 } })); return; } } setState(prev => ({ ...prev, meta: { ...prev.meta, isLoading: true, loadingProgress: 0, error: null } })); try { // 创建取消令牌 const abortController = new AbortController(); // 步骤1:加载项目数据 const projectData = await fetchProjectData(projectId, { signal: abortController.signal }); setState(prev => ({ ...prev, data: { ...prev.data, project: projectData }, meta: { ...prev.meta, loadingProgress: 20 } })); // 步骤2:加载用户数据 const userData = await fetchUserData(userId, { signal: abortController.signal }); setState(prev => ({ ...prev, data: { ...prev.data, user: userData }, meta: { ...prev.meta, loadingProgress: 40 } })); // 步骤3:并行加载权限和通知 const [permissions, notifications] = awaitPromise.all([ fetchUserPermissions(userId, projectData.id, { signal: abortController.signal }), fetchNotifications(userId, { signal: abortController.signal }) ]); setState(prev => ({ ...prev, data: { ...prev.data, permissions, notifications }, meta: { ...prev.meta, loadingProgress: 70 } })); // 步骤4:条件性加载分析数据 let analytics = null; if (permissions.includes('view_analytics')) { analytics = await fetchAnalytics(projectId, { signal: abortController.signal }); } const finalData = { project: projectData, user: userData, permissions, analytics, notifications }; // 更新缓存 if (enableCache) { cache.current.set(cacheKey, { data: finalData, timestamp: Date.now() }); } setState({ data: finalData, meta: { isLoading: false, isInitialized: true, loadingProgress: 100, error: null, retryCount: 0, lastUpdated: newDate() } }); return() => abortController.abort(); } catch (error) { if (error.name !== 'AbortError') { setState(prev => ({ ...prev, meta: { ...prev.meta, isLoading: false, error, retryCount: prev.meta.retryCount + 1 } })); } } }, [projectId, userId, cacheKey, enableCache]); // 自动重试逻辑 useEffect(() => { if (state.meta.error && enableRetry && state.meta.retryCount < maxRetries) { const timer = setTimeout(() => { loadData(); }, retryDelay * Math.pow(2, state.meta.retryCount - 1)); return() => clearTimeout(timer); } }, [state.meta.error, state.meta.retryCount, enableRetry, maxRetries, retryDelay, loadData]); // 初始化数据加载 useEffect(() => { loadData(); }, [loadData]); // 手动刷新函数 const refresh = useCallback(() => { if (enableCache) { cache.current.delete(cacheKey); } setState(prev => ({ ...prev, meta: { ...prev.meta, retryCount: 0 } })); loadData(); }, [loadData, cacheKey, enableCache]); return { ...state.data, ...state.meta, refresh }; } // 使用优化后的Hook function SuperOptimizedDashboard({ projectId, userId }) { const { project, user, permissions, analytics, notifications, isLoading, isInitialized, loadingProgress, error, refresh } = useDashboardData(projectId, userId, { enableRetry: true, maxRetries: 3, enableCache: true }); if (!isInitialized) { return<ProgressIndicator progress={loadingProgress} />; } if (error) { return<ErrorBoundary error={error} onRetry={refresh} />; } return ( <DashboardLayout> <ProjectSection data={project} /> <UserSection data={user} /> {permissions.includes('view_analytics') && ( <AnalyticsSection data={analytics} /> )} <NotificationsSection data={notifications} /> </DashboardLayout> ); }优化策略三:状态机模式处理复杂交互
// 定义状态机配置 const dashboardStateMachine = { idle: { on: { LOAD_START: 'loading', REFRESH: 'refreshing' } }, loading: { on: { LOAD_SUCCESS: 'loaded', LOAD_ERROR: 'error', LOAD_CANCEL: 'idle' } }, loaded: { on: { REFRESH: 'refreshing', UPDATE_DATA: 'updating', LOAD_ERROR: 'error' } }, refreshing: { on: { LOAD_SUCCESS: 'loaded', LOAD_ERROR: 'error', LOAD_CANCEL: 'loaded' } }, updating: { on: { UPDATE_SUCCESS: 'loaded', UPDATE_ERROR: 'error' } }, error: { on: { RETRY: 'loading', RESET: 'idle' } } }; function useStateMachine(initialState, stateMachine) { const [currentState, setCurrentState] = useState(initialState); const [context, setContext] = useState({}); const transition = useCallback((event, payload = {}) => { setCurrentState(prevState => { const nextState = stateMachine[prevState]?.on?.[event]; if (nextState) { setContext(payload); return nextState; } return prevState; }); }, [stateMachine]); const is = useCallback((state) => currentState === state, [currentState]); const can = useCallback((event) => { return !!stateMachine[currentState]?.on?.[event]; }, [currentState, stateMachine]); return { state: currentState, context, transition, is, can }; } // 使用状态机的组件 function StateMachineDashboard({ projectId, userId }) { const { state, context, transition, is, can } = useStateMachine('idle', dashboardStateMachine); const [data, setData] = useState({}); const loadData = useCallback(async () => { if (!can('LOAD_START') && !can('REFRESH') && !can('RETRY')) return; const isRefresh = is('loaded'); transition(isRefresh ? 'REFRESH' : 'LOAD_START'); try { // 数据加载逻辑 const result = await loadDashboardData(projectId, userId); setData(result); transition('LOAD_SUCCESS', { lastUpdated: newDate() }); } catch (error) { transition('LOAD_ERROR', { error }); } }, [projectId, userId, can, is, transition]); useEffect(() => { if (is('idle')) { loadData(); } }, [is, loadData]); const handleRetry = () => { if (can('RETRY')) { transition('RETRY'); loadData(); } }; const handleRefresh = () => { if (can('REFRESH')) { loadData(); } }; return ( <div> {is('loading') && <LoadingSpinner />} {is('refreshing') && <RefreshIndicator />} {is('error') && ( <ErrorDisplay error={context.error} onRetry={handleRetry} canRetry={can('RETRY')} /> )} {is('loaded') && ( <DashboardContent data={data} onRefresh={handleRefresh} canRefresh={can('REFRESH')} lastUpdated={context.lastUpdated} /> )} </div> ); }React 18并发特性的深度集成
function useConcurrentDashboardData(projectId, userId) { const [isPending, startTransition] = useTransition(); const [data, setData] = useState(null); const [error, setError] = useState(null); const deferredProjectId = useDeferredValue(projectId); const deferredUserId = useDeferredValue(userId); useEffect(() => { startTransition(async () => { try { setError(null); const result = await loadDashboardData(deferredProjectId, deferredUserId); setData(result); } catch (err) { setError(err); } }); }, [deferredProjectId, deferredUserId]); return { data, error, isPending }; } // Suspense集成 function SuspenseDashboard({ projectId, userId }) { return ( <Suspense fallback={<DashboardSkeleton />}> <ErrorBoundary> <DashboardContent projectId={projectId} userId={userId} /> </ErrorBoundary> </Suspense> ); }性能基准测试与对比分析
Cumulative Layout Shift 0.15 0.04 73.3%
useEffect(() => { const handleResize = () => setWindowSize(window.innerWidth); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []);2.第三方库集成
useEffect(() => { const chart = new Chart(canvasRef.current, config); return () => chart.destroy(); }, []);3.订阅和清理
useEffect(() => { const subscription = eventBus.subscribe('user-updated', handleUserUpdate); return () => subscription.unsubscribe(); }, []);❌ 应该避免使用useEffect的场景:
// 不好的做法 const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const [fullName, setFullName] = useState(''); useEffect(() => { setFullName(`${firstName} ${lastName}`); }, [firstName, lastName]); // 更好的做法 const [firstName, setFirstName] = useState(''); const [lastName, setLastName] = useState(''); const fullName = `${firstName} ${lastName}`;2.复杂的异步状态管理
// 不好的做法 - 多个useEffect处理相关状态 useEffect(() => { /* 获取用户数据 */ }, [userId]); useEffect(() => { /* 获取权限数据 */ }, [userData]); useEffect(() => { /* 处理加载状态 */ }, [userData, permissions]); // 更好的做法 - 使用自定义Hook或useReducer const { userData, permissions, isLoading } = useUserData(userId);性能优化决策树
开始 ↓ 是否需要处理副作用? ├─ 是 → 使用useEffect └─ 否 ↓ 是否有多个相关的状态需要同时更新? ├─ 是 → 考虑useReducer └─ 否 ↓ 是否需要复杂的异步逻辑? ├─ 是 → 创建自定义Hook └─ 否 ↓ 是否有复杂的状态转换? ├─ 是 → 考虑状态机模式 └─ 否 → 使用简单的useState渐进式重构策略
.设置代码审查检查点