如何将MSAL访问令牌传递给React Elastic Search的App连接器
问题根因
你遇到的报错核心原因是异步逻辑和React渲染机制的冲突:
getAccessToken是异步函数,执行时不会阻塞组件渲染流程,组件首次返回DOM的时候,令牌还没请求完成,config还是初始的undefined值,SearchProvider拿到空配置就会触发无连接器的报错。- 你用普通变量存储
config,哪怕后续异步请求完成给变量赋值,也不会触发组件重渲染,SearchProvider永远拿不到最新的有效配置。
解决方案
核心思路是用React的状态管理异步请求结果,等配置初始化完成再渲染搜索组件,具体步骤如下:
- 用
useState存储搜索配置和加载状态,配置更新时自动触发组件重渲染 - 把令牌获取的异步逻辑放到
useEffect中执行,避免重复请求 - 渲染时增加加载判断,配置未就绪时先展示加载状态,不要直接渲染
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
相关产品推荐
相关产品推荐

