React Admin集成ra-data-hasura:登录后需强制执行自省查询或刷新数据提供者
解决React Admin + ra-data-hasura登录后自省查询不更新的问题
ra-data-hasura的自省查询默认在创建数据提供者实例时执行,未登录时用访客角色获取的资源元数据会被缓存,登录后如果不重新初始化实例,就会导致新权限下的资源无法被识别。以下是几种可行的解决方式:
1. 登录后重新创建数据提供者实例(推荐)
将数据提供者的创建逻辑抽成可复用函数,登录成功后用新的认证信息重新生成实例,并替换React Admin使用的dataProvider。
实现步骤:
- 抽离创建dataProvider的函数,支持传入认证token
- 在应用根组件中维护dataProvider的状态,登录后更新该状态
- React Admin会自动监听dataProvider的变化,重新加载资源元数据
// utils/dataProvider.js import { buildHasuraProvider } from 'ra-data-hasura'; export const createHasuraDataProvider = async (authToken) => { const requestHeaders = authToken ? { Authorization: `Bearer ${authToken}` } : {}; return buildHasuraProvider({ clientOptions: { uri: 'https://your-hasura-endpoint/v1/graphql', headers: requestHeaders, }, }); };
// App.jsx import { useState, useEffect } from 'react'; import { Admin, Resource } from 'react-admin'; import { createHasuraDataProvider } from './utils/dataProvider'; import { LoginPage, authProvider } from './auth'; import { PostList } from './posts'; function App() { const [dataProvider, setDataProvider] = useState(null); const [isLoggedIn, setIsLoggedIn] = useState(false); // 初始化:创建访客角色的dataProvider useEffect(() => { const initDataProvider = async () => { const dp = await createHasuraDataProvider(null); setDataProvider(dp); }; initDataProvider(); }, []); // 登录成功后更新dataProvider const handleLoginSuccess = async (token) => { const newDataProvider = await createHasuraDataProvider(token); setDataProvider(newDataProvider); setIsLoggedIn(true); }; if (!dataProvider) return <div>加载中...</div>; return ( <Admin dataProvider={dataProvider} authProvider={authProvider} loginPage={() => <LoginPage onLoginSuccess={handleLoginSuccess} />} > {isLoggedIn && <Resource name="posts" list={PostList} />} </Admin> ); } export default App;
2. 手动触发自省查询(依赖ra-data-hasura版本)
部分版本的ra-data-hasura会在dataProvider实例上暴露introspect方法,可用于强制重新执行自省并更新内部资源缓存。同时需要更新请求头以带上登录后的认证信息。
// 登录组件内的处理逻辑 import { useDataProvider, useRefresh } from 'react-admin'; const LoginPage = () => { const dataProvider = useDataProvider(); const refresh = useRefresh(); const handleLogin = async (credentials) => { const token = await yourLoginLogic(credentials); // 更新dataProvider的请求头 dataProvider.client.setHeaders({ Authorization: `Bearer ${token}` }); // 强制执行自省查询 if (typeof dataProvider.introspect === 'function') { await dataProvider.introspect(); } // 刷新React Admin的资源状态 refresh(); }; // 登录表单渲染逻辑... };
注意:该方法兼容性较差,若你的ra-data-hasura版本未暴露introspect方法,建议使用第一种方案。
3. 确保请求头全局更新
如果上述方法仍有问题,需确认登录后所有GraphQL请求都带上了正确的角色/认证头。Hasura的角色权限是通过请求头(如x-hasura-role或Authorization)控制的,必须保证登录后的请求使用新的头信息。
内容的提问来源于stack exchange,提问作者Maria Fele
相关产品推荐
相关产品推荐

