React:让Context Provider全权处理异步调用与状态管理,消费者无需维护状态
实现无需Consumer管理状态的异步Feature Flag Provider/Consumer模式
核心思路
让Provider统一维护所有Feature Flag的加载状态和最终值,通过自定义hook封装状态获取与异步加载逻辑,Consumer只需调用hook获取状态,无需处理任何异步或状态管理代码。
实现代码
1. 重构Context Provider
import { createContext, useContext, useState, useCallback } from 'react'; // 初始化Context const FeaturesContext = createContext(); export function FeaturesProvider({ children }) { // 状态结构:{ [flagKey]: { loading: boolean, value: boolean } } const [featureFlags, setFeatureFlags] = useState({}); // 封装异步加载Feature Flag的逻辑 const loadFeatureFlag = useCallback(async (key) => { // 避免重复请求:已加载或正在加载时直接返回 const existingFlag = featureFlags[key]; if (existingFlag?.loading || existingFlag?.value !== undefined) return; // 标记为加载中 setFeatureFlags(prev => ({ ...prev, [key]: { loading: true, value: undefined } })); try { // 调用你的异步评估函数 const result = await evaluateFeatureFlag(key); setFeatureFlags(prev => ({ ...prev, [key]: { loading: false, value: result } })); } catch (err) { console.error(`加载Feature Flag ${key}失败:`, err); // 出错时默认设为禁用,可根据需求调整 setFeatureFlags(prev => ({ ...prev, [key]: { loading: false, value: false } })); } }, [featureFlags]); return ( <FeaturesContext.Provider value={{ featureFlags, loadFeatureFlag }}> {children} </FeaturesContext.Provider> ); }
2. 封装自定义Hook供Consumer使用
// 自定义Hook,简化Consumer调用 export function useFeatureFlag(key) { const { featureFlags, loadFeatureFlag } = useContext(FeaturesContext); // 默认状态:未加载时loading为false,value为undefined const currentFlag = featureFlags[key] || { loading: false, value: undefined }; // 首次使用该Flag时触发加载 useState(() => { if (!featureFlags[key]) { loadFeatureFlag(key); } }, [key, featureFlags, loadFeatureFlag]); return { loading: currentFlag.loading, isEnabled: currentFlag.value }; }
3. Consumer组件使用示例
import { useFeatureFlag } from './FeaturesProvider'; function MyCoolFeature() { const { loading, isEnabled } = useFeatureFlag('My_cool_feature'); // 加载中状态可自定义展示(比如骨架屏、加载提示) if (loading) { return <div>加载中...</div>; } return isEnabled ? <div>展示功能内容</div> : <div>功能已隐藏</div>; }
优势说明
- 状态完全集中管理:所有异步请求、状态更新都在Provider中处理,Consumer无需编写
useEffect或useState。 - 自动缓存与去重:已加载的Flag会被缓存,重复调用不会触发多次请求。
- 清晰的状态反馈:通过
loading状态可优雅处理加载过程,避免组件渲染异常。
内容的提问来源于stack exchange,提问作者Himmel
相关产品推荐
相关产品推荐

