
后端前端数据分析数据可视化【免费下载链接】growthbookOpen Source Feature Flags, Experimentation, and Product Analytics项目地址https://gitcode.com/gh_mirrors/gr/growthbook点击查看免费下载本篇基于 GrowthBook 官方前端开发指南>// packages/front-end/hooks/useApi.ts节选 return useSWRResponse, Error( allowed ? key : null, async () apiCallResponse(path, { method: GET }), config, );这意味着读写两条路径共用同一套请求封装Bearer token、X-Organization头、JWT 过期静默刷新前端组件只需关心各自的语义。读取数据useApi() 钩子基本用法useApi()是最主要的取数方式第一个参数是 API 路径支持内联查询参数泛型指定响应类型import useApi from /hooks/useApi; // 简单请求 const { data, error, mutate } useApi{ items: ItemInterface[] }(/items); // 带查询参数 const { data, error, mutate } useApi{ experiments: ExperimentInterface[] }( /experiments?project${project || }includeArchived${includeArchived ? 1 : }, );返回值说明data— 响应数据加载中为undefinederror— 请求失败时的 Error 对象mutate— 手动刷新/更新缓存的函数isLoading— SWR 提供的加载状态布尔值。完整选项含源码中比文档更多的 refreshIntervaluseApi.ts 导出的UseApiOptions定义了四个选项其中refreshInterval在官方指南中未列出但在源码中同样支持export interface UseApiOptionsResponse unknown { autoRevalidate?: boolean; shouldRun?: () boolean; orgScoped?: boolean; // 背景刷新的毫秒间隔也可以是一个根据最新数据返回下一间隔的函数 //返回 0 表示关闭。SWR 两种形式都支持。 refreshInterval?: number | ((latestData: Response | undefined) number); }各选项的默认值与生效逻辑源码 L13-L44选项默认值实现逻辑shouldRun不传即始终执行为false时 SWR key 被置为null请求不会发出autoRevalidatetrue设为false时同时关闭revalidateOnFocus与revalidateOnReconnectorgScopedtrue为true时缓存 key 加orgId ::前缀refreshInterval不设置透传给 SWR 的refreshInterval支持数值或动态间隔函数refreshInterval对实验结果页、时间序列图表这类需要周期性拉新数据的场景尤其有用组件只需传入间隔或根据最新数据动态计算的间隔函数即可获得后台轮询能力。条件请求shouldRun当请求依赖某个前置条件已登录、ID 已就绪时使用shouldRun// 仅在已认证时拉取 const { data } useApiUserResponse(/user, { shouldRun: () isAuthenticated, orgScoped: false, }); // 仅在拿到 ID 后拉取 const { data } useApiFeatureResponse(/feature/${featureId}, { shouldRun: () !!featureId, });源码层面shouldRun返回false时 SWR 收到的是nullkeyuseApi.ts L27、L41SWR 据此跳过请求条件恢复后会自动重新触发——这比手工if分支更符合 Hooks 调用规则。一个真实用例是 DefinitionsContext.tsx L204-L207全局定义只有在组织未被挂起且组织 ID 就绪时才拉取/organization/definitions。关闭自动再验证表单编辑、长驻编辑页等不希望焦点回到窗口就重新拉数据的场景可关闭自动再验证const { data, mutate } useApiDataResponse(/endpoint, { autoRevalidate: false, });对应源码中会把 SWR 的revalidateOnFocus和revalidateOnReconnect同时置为falseuseApi.ts L31-L34即窗口聚焦和网络重连都不会触发后台刷新数据只在你显式调用mutate()时更新。变更操作apiCall()POST/PUT/PATCH/DELETE 一律从useAuth()中取apiCallimport { useAuth } from /services/auth; function MyComponent() { const { apiCall } useAuth(); const handleCreate async () { await apiCall(/items, { method: POST, body: JSON.stringify({ name: New Item }), }); }; const handleUpdate async (id: string) { await apiCall(/items/${id}, { method: PUT, body: JSON.stringify({ name: Updated Name }), }); }; const handleDelete async (id: string) { await apiCall(/items/${id}, { method: DELETE, }); }; }apiCall的类型签名为(url: string, options?: RequestInit, errorHandler?) PromiseTauth.tsx L33-L37其中第二个参数直接接受原生RequestInit。变更成功后刷新缓存写操作不会自动失效读缓存标准做法是在await apiCall(...)之后调用对应useApi的mutate()function MyComponent() { const { apiCall } useAuth(); const { data, mutate } useApi{ items: ItemInterface[] }(/items); const handleCreate async (formData: CreateItemData) { try { await apiCall(/items, { method: POST, body: JSON.stringify(formData), }); // 创建后重新验证列表 await mutate(); } catch (e) { console.error(e); } }; }类型化响应apiCallT的泛型让返回值具备完整类型const response await apiCall{ item: ItemInterface; message?: string }( /items, { method: POST, body: JSON.stringify(data) }, ); console.log(response.item.id); // 已类型化源码深入apiCall 背后的鉴权与错误处理读 auth.tsx 的_makeApiCall与apiCall实现L380-L577可以看到官方文档中简单一行 await背后隐藏的完整机制请求封装_makeApiCall自动注入Authorization: Bearer token头L384有请求体但未显式指定时默认补Content-Type: application/jsonL387-L389因此示例代码里不必手写 Content-Type当前组织存在时注入X-Organization: orgId头L391-L393服务端据此做多组织数据隔离credentials按路径区分/api/v*形式的 REST API 路径走same-origin该 API 用 Authorization 头认证且允许任意 CORS 来源同站应用 API 走include可能位于 Cookie 认证的代理之后——见 isExternalApiPath 注释 L44-L49非 JSON 响应如 5xx HTML 页会抛出NonJsonResponseError避免解析失败时的模糊错误。JWT 过期自动刷新apiCall检测到status 400且message jwt expired时会先调用内部refreshToken()带并发去重全局同一时间只有一个刷新在途拿到新 token 后自动重放原请求若刷新返回的是 SSO 重定向则保存当前路径并跳转登录最后才抛出 Your session has expired 错误L519-L543。组件层通常不需要处理令牌过期。422 软警告Soft Warnings确认流后端可以返回422 warnings: string[]apiCall会暂停并弹出全局ApiWarningModal让用户确认用户选择继续时自动在 URL 上追加ignoreWarningstrueappendIgnoreWarnings L40-L42重新提交。并发多个警告请求会合并进同一个对话框pendingWarnings队列L492-L507。这意味着危险但允许强行保存的保存逻辑在 UI 层是开箱即用的。错误处理模式模式 1Try-Catch 本地错误状态const [error, setError] useStatestring | null(null); const handleSubmit async (data: FormData) { setError(null); try { const response await apiCall{ error?: string }(/endpoint, { method: POST, body: JSON.stringify(data), }); if (response.error) { setError(response.error); return; } mutate(); // 成功后刷新数据 } catch (e) { setError(e.message || An error occurred); } };注意apiCall抛出的Error.message通常已经过后端message字段加工见 auth.tsx L571可以直接展示给用户。模式 2交给 Modal 组件使用Modal组件时submit回调里抛出的错误会被组件自动捕获并展示无需手写错误 UIModal headerCreate Item submit{async () { await apiCall(/items, { method: POST, body: JSON.stringify(formData), }); mutate(); }} {/* 表单字段 */} /Modal模式 3读取侧检查 useApi 的 errorconst { data, error } useApiDataResponse(/endpoint); if (error) { return div classNamealert alert-danger{error.message}/div; } if (!data) { return LoadingSpinner /; } return MyContent data{data} /;常见进阶模式带加载态的列表const { data, error } useApi{ features: FeatureInterface[] }(/features); if (error) return ErrorDisplay error{error} /; if (!data) return LoadingOverlay /; return FeatureList features{data.features} /;乐观更新Optimistic Update先用mutate(newData, false)把新值写入缓存第二个参数false表示暂不发请求请求成功后再mutate()与服务器对齐失败时同样mutate()回滚const { data, mutate } useApi{ items: ItemInterface[] }(/items); const handleToggle async (id: string, enabled: boolean) { // 先乐观更新 UI mutate( { items: data.items.map((item) item.id id ? { ...item, enabled } : item, ), }, false, // 暂不重新验证 ); try { await apiCall(/items/${id}, { method: PUT, body: JSON.stringify({ enabled }), }); await mutate(); // 确认并重新验证 } catch (e) { await mutate(); // 出错回滚到服务端数据 } };一次刷新多个缓存多个列表受同一批量操作影响时并行调用各自的mutateconst { mutate: mutateFeatures } useApiFeaturesResponse(/features); const { mutate: mutateExperiments } useApiExperimentsResponse(/experiments); const handleBulkAction async () { await apiCall(/bulk-action, { method: POST, body: JSON.stringify(data) }); await Promise.all([mutateFeatures(), mutateExperiments()]); };刷新全局 Definitions 上下文metrics、fact tables、dimensions、saved groups 等定义类数据不挂在页面级useApi上而是集中在全局DefinitionsProvider中它用一个useApi(/organization/definitions)一次性拉取整组织的定义集合DefinitionsContext.tsx L204-L207并对每个集合派生出getMetricById、getConfigByKey等查找函数。修改这类数据后应调用mutateDefinitionsimport { useDefinitions } from /services/DefinitionsContext; function MyComponent() { const { apiCall } useAuth(); const { mutateDefinitions } useDefinitions(); const handleCreateMetric async () { await apiCall(/metrics, { method: POST, body: JSON.stringify(metricData), }); mutateDefinitions(); // 刷新全局 definitions 缓存 }; }mutateDefinitions的实现是 DefinitionsContext.tsx L448-L450mutate(Object.assign({ ...data }, changes), true)既支持传入局部changes做增量合并同文件的refreshTags即用它乐观追加新 tag也支持无参调用整体重新拉取。跨组件全局失效useSWRConfig 直接改缓存 key由于组织作用域缓存 key 的格式是orgId :: pathuseApi.ts L25任何组件都可以通过 SWR 的useSWRConfig直接失效任意缓存而不必持有对应的useApi实例。仓库中的真实用例 PowerCard.tsx L49-L50const { mutate } useSWRConfig(); // POST 之后手动失效实验详情缓存确保 dismissedWarnings 是最新的 mutate(${orgId}::/experiment/${experiment.id});AgentPanel.tsx 也用同样方式在 Agent 操作后批量刷新相关缓存。组织Organization作用域机制这是 GrowthBook 前端数据层最重要的设计。所有请求自动具备三层组织隔离请求头apiCall注入Authorization: Bearer token与X-Organization: orgIdauth.tsx L384-L393服务端据此确定数据归属缓存 key 前缀useApi默认把缓存 key 写成orgId :: pathuseApi.ts L25切换组织即自动失效因为 key 不同用户在 A、B 两个组织间切换时SWR 会按新 key 全新拉取不存在跨组织串数据的可能各组织的数据也各自独立缓存切回旧组织时无需重拉。需要全局非组织级数据的接口——如/user——传orgScoped: false关闭前缀即可。小结GrowthBook 前端的数据获取体系可以浓缩为四条规则读用useApi()SWR 封装组织作用域缓存、条件请求、自动再验证写用apiCall()自动鉴权、自动 JSON 头、JWT 过期重放、422 软警告确认流写成功后显式mutate()失效对应读缓存批量场景用Promise.all并行刷新定义类全局数据走useDefinitions()/mutateDefinitions()页面级组件外需要失效缓存时用useSWRConfig().mutate()直接操作orgId::pathkey错误处理优先交给Modal的submit或useApi的error仅在需要细粒度控制时才手写 try-catch 本地错误状态。核心实现只有三个文件建议对照阅读useApi.ts约 45 行的 SWR 封装、auth.tsx鉴权与 apiCall、DefinitionsContext.tsx全局定义缓存。赞分享后端前端数据分析数据可视化【免费下载链接】growthbookOpen Source Feature Flags, Experimentation, and Product Analytics项目地址https://gitcode.com/gh_mirrors/gr/growthbook点击查看免费下载相关推荐终极指南Homepage数据获取与SWR缓存策略详解终极指南Homepage数据获取与SWR缓存策略详解 Homepage是一个高度可定制的个人主页与应用程序仪表板集成了Docker和服务API。本文将深入探前端OpenMontage 前端请求自动去重实战SWR 数据获取模式详解OpenMontage 前端请求自动去重实战SWR 数据获取模式详解 导读 在 OpenMontage 这类集成了 Backlot UI、Remotion C人工智能AI Agent音视频媒体生成工作流自动化react-color与SWR集成数据获取与缓存策略react color与SWR集成数据获取与缓存策略 你是否在React项目中遇到过颜色选择器与远程数据同步的难题当用户从调色板选择颜色后如何高效保存到后前端UI组件上一篇CamemBERT法语 RoBERTa实战指南从 torch.hub 加载、Mask 填充到特征抽取与微调下一篇Ingress NGINX 外部认证响应头传播实战用 auth-url 与 auth-response-headers 把认证服务头部注入后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考