如何将React辅助函数重构为自定义Hook并适配Apollo Client?
重构fetchStatusCode为自定义Hook并结合Apollo Client动态设置请求头
第一步:重构为合规的自定义Hook useStatusCode
原辅助函数存在依赖缺失问题,且需遵循Hook命名规范(以use开头),重构后代码如下:
import { useEffect, useState } from 'react'; const useStatusCode = (url: string) => { const [statusText, setStatusText] = useState<string | null>(null); const [isLoading, setIsLoading] = useState(true); // 新增加载状态,用于后续判断请求完成时机 useEffect(() => { const fetchStatus = async () => { try { const response = await fetch(url); setStatusText(response.statusText); } catch (err) { console.error('获取状态文本失败:', err); setStatusText(null); } finally { setIsLoading(false); } }; fetchStatus(); }, [url]); // 补充url依赖,确保url变更时重新发起请求 return { statusText, isLoading }; }; export default useStatusCode;
第二步:在组件中结合Apollo Client动态更新请求头
Apollo Client默认的setContext逻辑是静态的,要让请求头响应statusText的变化,需将Client实例的创建逻辑放入组件内部,用useState管理实例,在statusText变化时重新生成Client:
import { ApolloClient, ApolloProvider, InMemoryCache, from, NormalizedCacheObject } from '@apollo/client'; import { setContext } from '@apollo/client/link/context'; import { useState, useEffect } from 'react'; import useStatusCode from './useStatusCode'; import errorLink from './errorLink'; import httpLink from './httpLink'; import typeDefs from './typeDefs'; const ApolloProviderWrapper = () => { const { statusText, isLoading } = useStatusCode('http://my-site.com/abc/token'); const [client, setClient] = useState<ApolloClient<NormalizedCacheObject> | null>(null); useEffect(() => { // 仅在请求完成后创建/更新Client if (!isLoading) { const isOkStatus = statusText === 'OK'; const myCustomLink = setContext((_, { headers }) => ({ headers: { ...headers, 'my-header': isOkStatus ? 'MyName' : null, }, })); const newClient = new ApolloClient({ link: from([errorLink, myCustomLink, httpLink]), cache: new InMemoryCache(), typeDefs, }); setClient(newClient); } }, [statusText, isLoading]); // 依赖statusText和加载状态,确保状态变更时同步更新Client // 请求未完成时显示加载态 if (isLoading || !client) { return <div>加载中...</div>; } return ( <ApolloProvider client={client}> {/* 应用业务组件 */} </ApolloProvider> ); }; export default ApolloProviderWrapper;
关键说明
- 自定义Hook必须严格遵循React Hook规则,正确声明依赖项,避免闭包导致的状态不一致问题。
- 通过
useState管理Apollo Client实例,确保statusText变化时能生成携带最新请求头的Client实例。 - 新增
isLoading状态,避免在状态文本请求未完成时创建无效的Client,提升稳定性。
内容的提问来源于stack exchange,提问作者meez
相关产品推荐
相关产品推荐

