如何在React单页应用中调用MS Graph Search API获取SharePoint列表项
前置准备
- 在Azure AD中注册**单页应用(SPA)**类型的应用:
- 添加与React应用匹配的重定向URI(比如本地开发用
http://localhost:3000) - 授予Delegated权限:
Sites.Read.All(只读)或Sites.ReadWrite.All(读写),并完成权限同意(管理员或用户同意,取决于权限类型)
- 添加与React应用匹配的重定向URI(比如本地开发用
配置认证(使用MSAL React)
微软官方推荐使用@azure/msal-react和@azure/msal-browser处理SPA的身份验证:
- 安装依赖:
npm install @azure/msal-react @azure/msal-browser
- 创建认证配置文件(
src/authConfig.js):
import { PublicClientApplication } from "@azure/msal-browser"; export const msalConfig = { auth: { clientId: "你的Azure AD应用ID", authority: "https://login.microsoftonline.com/你的租户ID", redirectUri: "http://localhost:3000" // 与注册的重定向URI一致 } }; export const msalInstance = new PublicClientApplication(msalConfig); export const graphEndpoint = "https://graph.microsoft.com/v1.0"; export const requiredScopes = ["Sites.Read.All"];
- 在根组件中包裹应用(
src/App.js):
import { MsalProvider } from "@azure/msal-react"; import { msalInstance } from "./authConfig"; import SharePointListViewer from "./SharePointListViewer"; function App() { return ( <MsalProvider instance={msalInstance}> <SharePointListViewer /> </MsalProvider> ); } export default App;
获取SharePoint列表项(直接调用Graph API)
创建组件SharePointListViewer.js,实现列表项获取逻辑:
import { useEffect, useState } from "react"; import { useMsal } from "@azure/msal-react"; import { requiredScopes, graphEndpoint } from "./authConfig"; const SharePointListViewer = () => { const [listItems, setListItems] = useState([]); const [isLoading, setIsLoading] = useState(true); const { instance, accounts } = useMsal(); const fetchListItems = async () => { const activeAccount = accounts[0]; if (!activeAccount) return; try { // 静默获取访问令牌 const tokenResponse = await instance.acquireTokenSilent({ account: activeAccount, scopes: requiredScopes }); // 替换为你的站点ID和列表ID // 站点ID可以是格式:`{domain}:/{site-path}:/`(例如`contoso.sharepoint.com:/sites/HRPortal:/`) const siteIdentifier = "你的站点ID"; const listId = "你的列表ID"; // 调用Graph API,按需指定要返回的字段 const apiUrl = `${graphEndpoint}/sites/${siteIdentifier}/lists/${listId}/items?$select=id,Title,Description`; const response = await fetch(apiUrl, { headers: { Authorization: `Bearer ${tokenResponse.accessToken}` } }); if (!response.ok) throw new Error(`请求失败: ${response.statusText}`); const data = await response.json(); setListItems(data.value); } catch (error) { // 静默获取令牌失败时,弹出登录窗口 if (error.name === "InteractionRequiredAuthError") { instance.acquireTokenPopup({ scopes: requiredScopes }); } else { console.error("获取列表项失败:", error); } } finally { setIsLoading(false); } }; useEffect(() => { fetchListItems(); }, [accounts, instance]); if (isLoading) return <div>加载中...</div>; return ( <div> <h2>SharePoint列表内容</h2> <ul> {listItems.map(item => ( <li key={item.id}> <h3>{item.Title}</h3> {item.Description && <p>{item.Description}</p>} </li> ))} </ul> </div> ); }; export default SharePointListViewer;
使用Graph Search API跨站点搜索列表项
如果需要跨多个站点搜索列表项,可以使用Graph Search API:
在SharePointListViewer.js中添加搜索逻辑:
const searchListItems = async (searchKeyword) => { const activeAccount = accounts[0]; if (!activeAccount || !searchKeyword) return; try { const tokenResponse = await instance.acquireTokenSilent({ account: activeAccount, scopes: requiredScopes }); const searchUrl = `${graphEndpoint}/search/query`; const response = await fetch(searchUrl, { method: "POST", headers: { Authorization: `Bearer ${tokenResponse.accessToken}`, "Content-Type": "application/json" }, body: JSON.stringify({ requests: [ { entityTypes: ["listItem"], query: { queryString: searchKeyword }, fields: ["id", "Title", "webUrl"], from: 0, size: 20 // 控制返回结果数量 } ] }) }); if (!response.ok) throw new Error(`搜索失败: ${response.statusText}`); const data = await response.json(); const searchResults = data.value[0].hitsContainers[0].hits.map(hit => hit.resource); setListItems(searchResults); } catch (error) { console.error("搜索列表项失败:", error); } };
关键注意事项
- 权限配置:确保Azure AD应用的权限已被正确同意,否则会返回403错误
- 站点/列表ID获取:可以通过Graph API的
GET /sites或GET /sites/{domain}:/{site-path}:/lists接口获取,也可从SharePoint列表页面的URL参数中提取ListId - CORS设置:在Azure AD应用的"API权限" -> "跨域资源共享(CORS)"中添加React应用的域名(比如
http://localhost:3000) - 错误处理:务必处理令牌过期、无权限、网络错误等场景,提升用户体验
内容的提问来源于stack exchange,提问作者Sonu
相关产品推荐
相关产品推荐

