Microsoft Graph Toolkit 在 React 中做集成

吕承望
2023-12-01

在更真实的世界中,应用程序一般都是基于框架开发,而不仅仅是HTML+JavaScript的。本篇就介绍一下如何在React框架中使用Microsoft Graph Toolkit,我们将编写一个简单的日程查看Web应用。

创建React的Web应用

首先我们当然是创建一个React的Web应用。
找一个喜欢的路径,打开命令行工具跳转到该目录,输入命令创建React项目。

npx create-react-app mgt-demo --template typescript

这里我们添加了template参数来告诉这个React项目使用TypeScript语言。
创建好之后通过命令npm install @microsoft/mgt –save添加Microsoft Graph Toolkit的npm库。

使用Microsoft Graph Toolkit Providers
我们可以根据实际的场景选择恰当的Provider,就像之前介绍的那样。本例中我们使用MsalProvider。打开App.tsx文件,添加以下代码,用于Provider的设置,将其中的[CLIENT_ID]换成我们真实的。

function App() { 
  const [isLoggedIn, setIsLoggedIn] = useState(false); 
  Providers.globalProvider = new MsalProvider({ clientId: '[CLIENT_ID]' }); 
  Providers.globalProvider.onStateChanged((e) => { 
    if (Providers.globalProvider.state !== ProviderState.Loading) 
      setIsLoggedIn(Providers.globalProvider.state === ProviderState.SignedIn); 
  }); 
  ... 
}

在React中使用Microsoft Graph Toolkit组件
在index.tsx文件中,添加以下声明:

declare global { 
  namespace JSX { 
    interface IntrinsicElements { 
      'mgt-login': any; 
      'mgt-agenda': any; 
      'mgt-person': any; 
    } 
  } 
}

通过上面这种方式,能够让我们的TSX识别Microsoft Graph Toolkit的组件标记以防止发生问题,如果有新的其他组件的需求,可以继续在IntrinsicElements接口中添加“'[COMPONENT NAME]’: any”这种格式的内容即可。

首先我们先写一个登录组件。

import React from 'react'; 
import '@microsoft/mgt'; 

const NavBar = () => { 
    return ( 
        <nav> 
            <mgt-login></mgt-login> 
        </nav> 
    ); 
} 

export default NavBar;

由于是示例这里只是简单地用了一下mgt-login的标签,如果想的话当然可以设置它的一些属性。

接下来添加mgt-agenda组件,我们计划使用自定义模板。但是这时我们会面临一个问题,那就是自定义模板中也会使用大括号{},这会产生冲突。

要解决这个问题有两个选项:

  1. 修改Microsoft Graph Toolkit中的绑定语法,这样操作:
import { TemplateHelper } from '@microsoft/mgt'; 
TemplateHelper.setBindingSyntax('[[', ']]');
  1. 第二种也是我们本例中使用的方式,使用data-属性直接进行DOM元素的绑定代码如下。
import React, { useRef, useEffect } from 'react'; 
import '@microsoft/mgt'; 

const AgendaWC = () => { 
    const agendaRef = useRef<any>(null); 

    useEffect(() => { 
        agendaRef.current.templateContext = { 
            openWebLink: (e: any, context: { event: { webLink: string | undefined; }; }, root: any) => { 
                window.open(context.event.webLink, '_blank'); 
            }, 
            getDate: (dateString: string) => { 
                let dateObject = new Date(dateString); 
                return dateObject.setHours(0, 0, 0, 0); 
            }, 
            getTime: (dateString: string) => { 
                let dateObject = new Date(dateString); 
                return dateObject.getHours().toString().padStart(2, '0') + ':' + dateObject.getMinutes().toString().padStart(2, '0'); 
            } 
        } 
    }, []); 

    return ( 
        <mgt-agenda group-by-day ref={agendaRef}> 
            <template data-type="event"> 
                <div className="..."> 
                    <div className="..." 
                        data-props="{{@click: openWebLink, innerHTML: event.subject}}" /> 
                    <div className="..." data-if="getDate(event.start.dateTime) == getDate(event.end.dateTime)" 
                        data-props="{{innerHTML: 'from ' + getTime(event.start.dateTime) + ' to ' + getTime(event.end.dateTime)}}" /> 
                    <div className="..." data-if="event.body.content != ''" 
                        data-props="{{innerHTML: event.body.content}}" /> 
                </div> 
            </template> 
            <template data-type="no-data"> 
                <div className="..."> 
                    No events to show 
              </div> 
            </template> 
        </mgt-agenda> 
    ); 
} 

export default AgendaWC;

至此,我们可以将上面提到的两个组件放到"App"中了:

import React, { useState } from 'react'; 
import { Providers, MsalProvider, ProviderState } from '@microsoft/mgt'; 
import NavBar from './navBar' 
import AgendaWC from './agendaWC' 
 
function App() { 
  const [isLoggedIn, setIsLoggedIn] = useState(false); 
  Providers.globalProvider = new MsalProvider({ clientId: [CLIENT_ID]' }); 
  Providers.globalProvider.onStateChanged((e) => { 
    if (Providers.globalProvider.state !== ProviderState.Loading) 
      setIsLoggedIn(Providers.globalProvider.state === ProviderState.SignedIn); 
  }); 
 
  return ( 
    <div> 
      <NavBar /> 
      {(isLoggedIn) ? 
        <div className="..."> 
          <div> 
            <h1 className="..."> 
              Agenda 
            </h1> 
            <AgendaWC /> 
          </div> 
        </div> 
        : 
        <div className="..."> 
          Login to show data 
        </div> 
      } 
    </div> 
  ); 
} 
 
export default App;

通过mgt-react使用Microsoft Graph Toolkit
一种在React中集成Microsoft Graph Toolkit更简洁的方式是使用mgt-react库,这个库实际上是将Microsoft Graph Toolkit的组件封装了一层,我们看一下如何使用。

首先添加npm包:

npm install mgt-react -–save

然后引入我们想要使用的组件:

import { Agenda, MgtTemplateProps } from 'mgt-react';

Microsoft Graph Toolkit的所有组件都在React组件中做了相应的映射。

在模板部分,跟前面介绍的就不一样了,我们可以充分利用React的强大了。

我们可以首先定义一个包含MgtTemplaeProps对象的React组件:

import { MgtTemplateProps } from 'mgt-react'; 

const MyEvent = (props: MgtTemplateProps) => { 
  const { event } = props.dataContext; 
  return <div>{event.subject}</div>; 
};

然后在Agenda的组件中这样使用模板:

import { Agenda } from 'mgt-react'; 
 
const App = (props) => { 
  return <Agenda> 
    <MyEvent template="event"> 
  </Agenda> 
}

通过这样的方式,我们之前的代码就可以写成下面这样:

import React from 'react'; 
import '@microsoft/mgt'; 
import { Agenda, MgtTemplateProps } from 'mgt-react'; 
 
const AgendaReact = () => { 
    return ( 
        <Agenda groupByDay={true} > 
            <Event template="event" /> 
            <NoData template="no-data" /> 
        </Agenda> 
    ); 
} 
 
const Event = (props: MgtTemplateProps) => { 
    const { event } = props.dataContext; 
    const openWebLink = () => { 
        window.open(event.webLink, '_blank'); 
    }; 
 
    const getDate = (dateString: string) => { 
        let dateObject = new Date(dateString); 
        return dateObject.setHours(0, 0, 0, 0); 
    }; 
 
    const getTime = (dateString: string) => { 
        let dateObject = new Date(dateString); 
        return dateObject.getHours().toString().padStart(2, '0') 
            + ':' + 
            dateObject.getMinutes().toString().padStart(2, '0'); 
    }; 
 
    return ( 
        <div className="..."> 
            <div className="..." onClick={() => { openWebLink(); }}> 
                {event.subject} 
            </div> 
            {(getDate(event.start.dateTime) 
                == getDate(event.end.dateTime)) ? 
                <div className="..."> 
                    from {getTime(event.start.dateTime)} 
                    to {getTime(event.end.dateTime)} 
                </div> 
                : null 
            } 
            {(event.body.content != '') ? 
                <div className="..." 
                    dangerouslySetInnerHTML={{ __html: event.body.content }} /> 
                : null 
            } 
        </div> 
    ); 
}; 
 
const NoData = (props: MgtTemplateProps) => { 
    return <div className="..."> 
        No events to show 
      </div> 
}; 
 
export default AgendaReact;

向React应用添加样式
显然之前我们没有提及这个示例样式方面的内容。因为Microsoft Graph Toolkit组件自身已经具有样式,但是当我们使用模板时,我们需要为定义的模板指定样式。

这里就不做展示了,但是为大家介绍一个比较有趣的CSS框架,Tailwind CSS,安装它。

npm install tailwindcss -–save

使用前我们要先在src根目录创建一个CSS文件如tailwind.css并添加如下内容:

@tailwind base; 
@tailwind components; 
@tailwind utilities;

这样Tailwind CSS编译器就能够生成相应的样式内容。

至于使用什么样的样式大家可以自行了解后去尝试了。
Tailwind CSS官网:https://tailwindcss.com/

微软官方完整的React应用代码示例地址:
https://github.com/microsoftgraph/mgtLap-TryItOut

 类似资料: