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

如何将MSAL访问令牌传递给React Elastic Search的App连接器

问题根因

你遇到的报错核心原因是异步逻辑和React渲染机制的冲突:

  • getAccessToken是异步函数,执行时不会阻塞组件渲染流程,组件首次返回DOM的时候,令牌还没请求完成,config还是初始的undefined值,SearchProvider拿到空配置就会触发无连接器的报错。
  • 你用普通变量存储config,哪怕后续异步请求完成给变量赋值,也不会触发组件重渲染,SearchProvider永远拿不到最新的有效配置。

解决方案

核心思路是用React的状态管理异步请求结果,等配置初始化完成再渲染搜索组件,具体步骤如下:

  1. 用useState存储搜索配置和加载状态,配置更新时自动触发组件重渲染
  2. 把令牌获取的异步逻辑放到useEffect中执行,避免重复请求
  3. 渲染时增加加载判断,配置未就绪时先展示加载状态,不要直接渲染SearchProvider

修改后的代码示例

import { useState, useEffect } from 'react';

export default function App() {
  const isAuthenticated = useIsAuthenticated();
  const { instance, accounts, inProgress } = useMsal();
  const { hostIdentifier, endpointBase, engineName } = getConfig();
  // 新增状态存储搜索配置和加载状态
  const [searchConfig, setSearchConfig] = useState(null);
  const [loading, setLoading] = useState(true);

  // 原有登录逻辑保持不变
  if (!isAuthenticated && inProgress === InteractionStatus.None) {
    instance.loginRedirect(loginRequest).catch(e => {
      console.error(e);
    });
  }

  // 异步获取令牌并初始化配置
  useEffect(() => {
    // 账号不存在时跳过执行
    if (!accounts[0]) return;

    const initSearchConfig = async () => {
      try {
        const request = {
          scopes: ['api://.....'],
          account: accounts[0]
        };
        // 静默获取访问令牌
        const tokenResponse = await instance.acquireTokenSilent(request);
        // 初始化App Search连接器
        const connector = new AppSearchAPIConnector({
          searchKey: tokenResponse.accessToken,
          engineName,
          hostIdentifier,
          endpointBase,
        });
        // 生成完整搜索配置
        const config = {
          searchQuery: {
            facets: buildFacetConfigFromConfig(),
            ...buildSearchOptionsFromConfig(),
          },
          autocompleteQuery: buildAutocompleteQueryConfig(),
          apiConnector: connector,
          alwaysSearchOnInitialLoad: false,
        };
        // 配置存入状态触发重渲染
        setSearchConfig(config);
      } catch (err) {
        // 静默获取令牌失败兜底,触发重定向拿新令牌
        console.error('访问令牌获取失败', err);
        instance.acquireTokenRedirect(loginRequest).catch(e => console.error(e));
      } finally {
        setLoading(false);
      }
    };

    initSearchConfig();
  }, [accounts, instance, engineName, hostIdentifier, endpointBase]);

  // 配置未就绪时展示加载状态
  if (loading || !searchConfig) {
    return <div>加载中,请稍候...</div>;
  }

  return (
    <PageLayout>
      <AuthenticatedTemplate>
        <SearchProvider config={searchConfig}>
          <WithSearch
            mapContextToProps={({ wasSearched }) => ({ wasSearched })}
            {/* 原有业务逻辑保持不变 */}
          />
        </SearchProvider>
      </AuthenticatedTemplate>
    </PageLayout>
  );
}

额外注意点

  • 你原有代码中重复声明了searchKey和connector变量,注意不要和getConfig返回的参数重名造成变量覆盖
  • 可以根据业务需求自定义加载状态的UI,避免用户等待时看到空白页面

内容的提问来源于stack exchange,提问作者Pradeep

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:15:03