ReactJS应用中如何集中存储API URI?环境可配置方案咨询
嘿,这个问题我太熟了!不用Redux也完全能搞定,给你几个项目里实际在用的常规方案,从简单到进阶都有:
方案1:创建集中式配置文件(最常用)
这是最基础也最省心的方式,把所有API相关配置放到单独文件里,组件里直接导入就行,不用每次写process.env。
- 新建配置文件,比如
src/config/api.js:
// src/config/api.js // 优先用环境变量,没有的话给个默认值(比如本地开发地址) export const API_BASE_URI = process.env.REACT_APP_SERVICE_URI || 'http://localhost:3001/api'; // 还可以顺便加其他API相关配置,比如超时时间、默认请求头 export const API_TIMEOUT = 10000; export const DEFAULT_HEADERS = { 'Content-Type': 'application/json', };
- 在需要调用API的组件/工具里导入:
import { API_BASE_URI, DEFAULT_HEADERS } from '../config/api'; const fetchUsers = async () => { const response = await fetch(`${API_BASE_URI}/users`, { headers: DEFAULT_HEADERS, }); return response.json(); };
这种方式的好处是集中管理,以后要改URI或者加新配置,只需要改这一个文件就行,不用全局搜代码。
方案2:封装自定义Hook(进阶优化)
如果你的API调用逻辑比较多,可以把URI和请求逻辑一起封装成Hook,进一步简化组件代码,还能统一处理错误、加载状态。
- 新建Hook文件
src/hooks/useApi.js:
import { API_BASE_URI, DEFAULT_HEADERS } from '../config/api'; import { useState } from 'react'; export const useApi = () => { const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const callApi = async (endpoint, options = {}) => { setIsLoading(true); setError(null); const url = `${API_BASE_URI}${endpoint}`; try { const response = await fetch(url, { headers: { ...DEFAULT_HEADERS, ...options.headers }, ...options, }); if (!response.ok) { throw new Error(`HTTP错误:${response.status}`); } return await response.json(); } catch (err) { setError(err.message); throw err; // 抛出错误让组件自己处理 } finally { setIsLoading(false); } }; return { callApi, isLoading, error }; };
- 组件里使用:
import { useApi } from '../hooks/useApi'; const UserList = () => { const { callApi, isLoading, error } = useApi(); const [users, setUsers] = useState([]); const loadUsers = async () => { try { const data = await callApi('/users'); setUsers(data); } catch (err) { // 这里可以做弹窗提示等操作 } }; return ( <div> <button onClick={loadUsers} disabled={isLoading}> {isLoading ? '加载中...' : '加载用户'} </button> {error && <p className="error">{error}</p>} <ul>{users.map(u => <li key={u.id}>{u.name}</li>)}</ul> </div> ); };
这个方案不仅集中了URI,还统一了请求的加载、错误处理逻辑,组件代码会干净很多。
方案3:用Context API(适合动态切换场景)
如果你的应用需要运行时切换API URI(比如给用户提供环境切换按钮),那Context API就派上用场了,能让全局组件都拿到最新的URI。
- 创建Context文件
src/contexts/ApiContext.js:
import { createContext, useContext, useState, useEffect } from 'react'; const ApiContext = createContext(); export const ApiProvider = ({ children }) => { // 初始化URI:优先用本地存储(用户上次设置),再用环境变量,最后给默认值 const [apiBaseUri, setApiBaseUri] = useState(() => { return localStorage.getItem('api_uri') || process.env.REACT_APP_SERVICE_URI || 'http://localhost:3001/api'; }); // 暴露切换URI的方法 const updateApiUri = (newUri) => { setApiBaseUri(newUri); localStorage.setItem('api_uri', newUri); // 保存到本地,下次打开保持设置 }; return ( <ApiContext.Provider value={{ apiBaseUri, updateApiUri }}> {children} </ApiContext.Provider> ); }; // 自定义Hook简化调用 export const useApiContext = () => useContext(ApiContext);
- 在根组件
App.js里包裹Provider:
import { ApiProvider } from './contexts/ApiContext'; function App() { return ( <ApiProvider> {/* 你的所有应用组件 */} </ApiProvider> ); }
- 组件里使用:
import { useApiContext } from '../contexts/ApiContext'; const EnvSwitcher = () => { const { apiBaseUri, updateApiUri } = useApiContext(); return ( <div> <input type="text" value={apiBaseUri} onChange={(e) => updateApiUri(e.target.value)} placeholder="输入API地址" /> </div> ); };
这个方案适合有动态配置需求的场景,一般小项目用前两个方案就足够了。
最后补充下环境变量的配置:React默认支持.env系列文件,比如.env.development(开发环境)、.env.production(生产环境),在文件里写REACT_APP_SERVICE_URI=http://dev-api.example.com,启动项目时会自动加载对应环境的变量,非常方便。
内容的提问来源于stack exchange,提问作者El Mac
相关产品推荐
相关产品推荐

