Sandbox/Production模式切换时,如何实现视图及API调用切换?
实现模式切换时同步切换API地址与视图
1. 全局共享模式状态
为了让导航栏的模式状态能在API调用、视图组件等全局场景访问,用React Context实现状态全局共享,同时持久化到localStorage避免刷新丢失:
// src/contexts/ModeContext.js import { createContext, useContext, useState, useEffect } from 'react'; const ModeContext = createContext(); export function ModeProvider({ children }) { // true = Sandbox模式, false = Production模式 const [isSandboxMode, setIsSandboxMode] = useState(true); // 切换模式函数 const toggleMode = () => { setIsSandboxMode(prev => !prev); // 持久化到localStorage localStorage.setItem('appMode', isSandboxMode ? 'production' : 'sandbox'); }; // 初始化时从localStorage恢复状态 useEffect(() => { const savedMode = localStorage.getItem('appMode'); if (savedMode) { setIsSandboxMode(savedMode === 'sandbox'); } }, []); return ( <ModeContext.Provider value={{ isSandboxMode, toggleMode }}> {children} </ModeContext.Provider> ); } // 自定义Hook方便组件调用 export function useMode() { return useContext(ModeContext); }
在根组件(如App.js)中包裹所有内容:
import { ModeProvider } from './contexts/ModeContext'; function App() { return ( <ModeProvider> {/* 导航栏、仪表盘等所有组件 */} </ModeProvider> ); }
2. 改造导航栏切换开关
用自定义Hook替换原有的局部状态,实现全局状态联动:
import { Switch, Text } from '@chakra-ui/react'; import { useMode } from '../contexts/ModeContext'; function ModeToggle() { const { isSandboxMode, toggleMode } = useMode(); return ( <> <Text fontSize={15} mr={2}> {isSandboxMode ? "Sandbox" : "Production"} </Text> <Switch onChange={toggleMode} isChecked={isSandboxMode} /> </> ); }
3. 统一API地址管理与Axios实例封装
创建API配置文件,根据当前模式自动切换基础地址,同时封装Axios实例统一处理请求头:
// src/services/apiConfig.js import axios from 'axios'; import { useMode } from '../contexts/ModeContext'; // 获取当前模式对应的API基础URL export function useApiBaseUrl() { const { isSandboxMode } = useMode(); return isSandboxMode ? import.meta.env.VITE_BACKEND_SANDBOX_URL : import.meta.env.VITE_BACKEND_PRODUCTION_URL; } // 封装带自动切换地址的Axios实例 export function useApiClient() { const baseUrl = useApiBaseUrl(); const apiClient = axios.create({ baseURL: baseUrl, }); // 统一添加Authorization请求头(示例) apiClient.interceptors.request.use(config => { const token = localStorage.getItem('authToken'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); return apiClient; }
4. 改造API调用函数
基于封装的Axios实例,替换硬编码的API地址:
// src/services/customerService.js import { useApiClient } from './apiConfig'; // 封装客户相关API export function useCustomerService() { const apiClient = useApiClient(); const getAllCustomers = async (rows, page) => { const response = await apiClient.get( `/api/v1/customer/paginate-customer?page=${page}&rows=${rows}` ); return response.data; }; return { getAllCustomers }; }
在组件中调用示例:
import { useCustomerService } from './services/customerService'; function CustomerList() { const { getAllCustomers } = useCustomerService(); // 调用接口 const fetchCustomers = async () => { const data = await getAllCustomers(10, 1); // 处理数据 }; return <div>{/* 渲染客户列表 */}</div>; }
5. 视图切换实现
根据全局模式状态,控制不同模式下的视图展示:
方式1:分组件渲染
import { useMode } from '../contexts/ModeContext'; import SandboxDashboard from './SandboxDashboard'; import ProductionDashboard from './ProductionDashboard'; function Dashboard() { const { isSandboxMode } = useMode(); return isSandboxMode ? <SandboxDashboard /> : <ProductionDashboard />; }
方式2:组件内局部控制
import { useMode } from '../contexts/ModeContext'; function Dashboard() { const { isSandboxMode } = useMode(); return ( <div> {/* Sandbox模式专属标识 */} {isSandboxMode && <span style={{ color: '#ff4d4f', marginRight: 8 }}>【Sandbox环境】</span>} {/* 通用内容 */} <div>仪表盘通用内容</div> {/* Production模式专属组件 */} {!isSandboxMode && <ProductionAnalytics />} </div> ); }
内容的提问来源于stack exchange,提问作者user21845082
相关产品推荐
相关产品推荐

