refactor: 重构 App.js 使用 AppProviders 和 GlobalComponents
- 使用 useGlobalErrorHandler Hook 替代内联错误处理 - 使用 AppProviders 替代 6 层 Provider 嵌套 - 使用 GlobalComponents 替代分散的全局组件 - 简化 AppContent,只保留 PostHog 初始化和路由渲染 效果: - App.js 从 165 行减少到 62 行 (-62%) - 总计从原始 330 行减少到 62 行 (-81%) - 代码结构清晰,职责分明 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
151
src/App.js
151
src/App.js
@@ -10,81 +10,30 @@
|
||||
*/
|
||||
|
||||
import React, { useEffect } from "react";
|
||||
import { ChakraProvider } from '@chakra-ui/react';
|
||||
|
||||
// Core Components
|
||||
import theme from "theme/theme.js";
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
// Routes
|
||||
import AppRoutes from './routes';
|
||||
|
||||
// Redux
|
||||
import { Provider as ReduxProvider } from 'react-redux';
|
||||
import { store } from './store';
|
||||
|
||||
// Contexts
|
||||
import { AuthProvider } from "contexts/AuthContext";
|
||||
import { AuthModalProvider } from "contexts/AuthModalContext";
|
||||
import { NotificationProvider, useNotification } from "contexts/NotificationContext";
|
||||
// Providers
|
||||
import AppProviders from './providers/AppProviders';
|
||||
|
||||
// Components
|
||||
import ErrorBoundary from "components/ErrorBoundary";
|
||||
import AuthModalManager from "components/Auth/AuthModalManager";
|
||||
import NotificationContainer from "components/NotificationContainer";
|
||||
import ConnectionStatusBar from "components/ConnectionStatusBar";
|
||||
import NotificationTestTool from "components/NotificationTestTool";
|
||||
import ScrollToTop from "components/ScrollToTop";
|
||||
import { logger } from "utils/logger";
|
||||
import GlobalComponents from './components/GlobalComponents';
|
||||
|
||||
// PostHog Redux 集成
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { initializePostHog } from "store/slices/posthogSlice";
|
||||
// Hooks
|
||||
import { useGlobalErrorHandler } from './hooks/useGlobalErrorHandler';
|
||||
|
||||
// Redux
|
||||
import { initializePostHog } from './store/slices/posthogSlice';
|
||||
|
||||
// Utils
|
||||
import { logger } from './utils/logger';
|
||||
|
||||
/**
|
||||
* ConnectionStatusBar 包装组件
|
||||
* 需要在 NotificationProvider 内部使用,所以单独提取
|
||||
* AppContent - 应用核心内容
|
||||
* 负责 PostHog 初始化和渲染路由
|
||||
*/
|
||||
function ConnectionStatusBarWrapper() {
|
||||
const { connectionStatus, reconnectAttempt, maxReconnectAttempts, retryConnection } = useNotification();
|
||||
const [isDismissed, setIsDismissed] = React.useState(false);
|
||||
|
||||
// 监听连接状态变化
|
||||
React.useEffect(() => {
|
||||
// 重连成功后,清除 dismissed 状态
|
||||
if (connectionStatus === 'connected' && isDismissed) {
|
||||
setIsDismissed(false);
|
||||
// 从 localStorage 清除 dismissed 标记
|
||||
localStorage.removeItem('connection_status_dismissed');
|
||||
}
|
||||
|
||||
// 从 localStorage 恢复 dismissed 状态
|
||||
if (connectionStatus !== 'connected' && !isDismissed) {
|
||||
const dismissed = localStorage.getItem('connection_status_dismissed');
|
||||
if (dismissed === 'true') {
|
||||
setIsDismissed(true);
|
||||
}
|
||||
}
|
||||
}, [connectionStatus, isDismissed]);
|
||||
|
||||
const handleClose = () => {
|
||||
// 用户手动关闭,保存到 localStorage
|
||||
setIsDismissed(true);
|
||||
localStorage.setItem('connection_status_dismissed', 'true');
|
||||
logger.info('App', 'Connection status bar dismissed by user');
|
||||
};
|
||||
|
||||
return (
|
||||
<ConnectionStatusBar
|
||||
status={connectionStatus}
|
||||
reconnectAttempt={reconnectAttempt}
|
||||
maxReconnectAttempts={maxReconnectAttempts}
|
||||
onRetry={retryConnection}
|
||||
onClose={handleClose}
|
||||
isDismissed={isDismissed}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function AppContent() {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@@ -94,73 +43,21 @@ function AppContent() {
|
||||
logger.info('App', 'PostHog Redux 初始化已触发');
|
||||
}, [dispatch]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* Socket 连接状态条 */}
|
||||
<ConnectionStatusBarWrapper />
|
||||
|
||||
{/* 路由切换时自动滚动到顶部 */}
|
||||
<ScrollToTop />
|
||||
|
||||
{/* 应用路由 - 从 routes/index.js 导入 */}
|
||||
<AppRoutes />
|
||||
</>
|
||||
);
|
||||
return <AppRoutes />;
|
||||
}
|
||||
|
||||
/**
|
||||
* App - 应用根组件
|
||||
* 设置全局错误处理,提供 Provider 和全局组件
|
||||
*/
|
||||
export default function App() {
|
||||
// 全局错误处理:捕获未处理的 Promise rejection
|
||||
useEffect(() => {
|
||||
const handleUnhandledRejection = (event) => {
|
||||
logger.error('App', 'unhandledRejection', event.reason instanceof Error ? event.reason : new Error(String(event.reason)), {
|
||||
promise: event.promise
|
||||
});
|
||||
// 阻止默认的错误处理(防止崩溃)
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
const handleError = (event) => {
|
||||
logger.error('App', 'globalError', event.error || new Error(event.message), {
|
||||
filename: event.filename,
|
||||
lineno: event.lineno,
|
||||
colno: event.colno
|
||||
});
|
||||
// 阻止默认的错误处理(防止崩溃)
|
||||
event.preventDefault();
|
||||
};
|
||||
|
||||
window.addEventListener('unhandledrejection', handleUnhandledRejection);
|
||||
window.addEventListener('error', handleError);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('unhandledrejection', handleUnhandledRejection);
|
||||
window.removeEventListener('error', handleError);
|
||||
};
|
||||
}, []);
|
||||
// 全局错误处理
|
||||
useGlobalErrorHandler();
|
||||
|
||||
return (
|
||||
<ReduxProvider store={store}>
|
||||
<ChakraProvider
|
||||
theme={theme}
|
||||
toastOptions={{
|
||||
defaultOptions: {
|
||||
position: 'top',
|
||||
duration: 3000,
|
||||
isClosable: true,
|
||||
}
|
||||
}}
|
||||
>
|
||||
<ErrorBoundary>
|
||||
<NotificationProvider>
|
||||
<AuthProvider>
|
||||
<AppProviders>
|
||||
<AppContent />
|
||||
<AuthModalManager />
|
||||
<NotificationContainer />
|
||||
<NotificationTestTool />
|
||||
</AuthProvider>
|
||||
</NotificationProvider>
|
||||
</ErrorBoundary>
|
||||
</ChakraProvider>
|
||||
</ReduxProvider>
|
||||
<GlobalComponents />
|
||||
</AppProviders>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user