You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 07:00:58