Проблема MS Graph API с React

#reactjs #microsoft-graph-api

Вопрос:

Я работаю над проектом React.

Я могу войти в API graph, также могу получать контакты пользователя, но не могу получать события его календаря.

конфигурационный файл:

 export const msalConfig = {
  auth: {
    clientId: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
    authority: "https://login.microsoftonline.com/common",
    redirectUri: "http://localhost:4200",
  },
  cache: {
    cacheLocation: "sessionStorage", // This configures where your cache will be stored
    storeAuthStateInCookie: true, // Set this to "true" if you are having issues on IE11 or Edge
  }
};

// Add scopes here for ID token to be used at Microsoft identity platform endpoints.
export const loginRequest = {
 scopes: ["Calendars.ReadWrite", "Contacts.Read"]
};

// Add the endpoints here for Microsoft Graph API services you'd like to use.
export const graphConfig = {
  graphMeEndpoint: "https://graph.microsoft.com/v1.0/me",
  graphCalendarsEndpoint: "https://graph.microsoft.com/v1.0/me/events",
  graphContactsEndpoint: "https://graph.microsoft.com/v1.0/me/contacts",
};
 

1/ Рабочая часть

файл importContact.jsx:

 ...
import { loginRequest, graphConfig } from '../authConfig.jsx';
import { useMsal } from "@azure/msal-react";

const ImportContacts = (props) => {
    const { instance, accounts, inProgress } = useMsal();
    const [accessToken, setAccessToken] = useState(null);
    const [graphData, setGraphData] = useState(null);

    const getMicrosoftContacts = () => {
    const request = {
        ...loginRequest,
        account: accounts[0]
    };
    var contacts= [];

  // Silently acquires an access token which is then attached to a request for Microsoft Graph data
  instance.acquireTokenSilent(request).then((response) => {
    console.log('acquireTokenSilent')
      setAccessToken(response.accessToken);
      callMsGraph(response.accessToken).then(
        response => {
          setGraphData(response);
          console.log(response)
          for (const item of response.value){
            contacts.push({
                provider: 'Microsoft',
                id: item.id,
                email: item.emailAddresses[0].address,
                firstName: item.givenName,
                lastName: item.surname,
                name: item.displayName,
                label:item.displayName   " ("   item.emailAddresses[0].address   ")" }
              )
          }
          setItems(contacts);
        }
        );
  }).catch((e) => {
      instance.acquireTokenPopup(request).then((response) => {
          setAccessToken(response.accessToken);
          callMsGraph(response.accessToken).then(
            response => {
              setGraphData(response);
              for (const item of response.value){
                contacts.push({
                    provider: 'Microsoft',
                    id: item.id,
                    email: item.emailAddresses[0].address,
                    firstName: item.givenName,
                    lastName: item.surname,
                    name: item.displayName,
                    label:item.displayName }
                  )
              }
              setItems(contacts);
            }
            );
          });
      });
    }

    async function callMsGraph(accessToken) {
    const headers = new Headers();
    const bearer = `Bearer ${accessToken}`;

    headers.append("Authorization", bearer);

    const options = {
        method: "GET",
        headers: headers
    };

    return fetch(graphConfig.graphContactsEndpoint, options)
        .then(response => response.json())
        .catch(error => console.log(error));
    }
    ...
}
 

2/ Нерабочая часть в файле events.jsx:

 ...
import { loginRequest, graphConfig } from '../authConfig.jsx';
import { useMsal } from "@azure/msal-react";

class Events extends Component {

    constructor(props) {
        super(props);
        this.getMicrosoftEvents = this.getMicrosoftEvents.bind(this);
    }

    componentDidMount(){
        var date = new Date();
        var firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
        var lastDay = new Date(date.getFullYear(), date.getMonth()   1, 0);
        this.getMicrosoftEvents(firstDay, lastDay);
    }

    getMicrosoftEvents(start, end) {
        console.log('log displayed in console')

        const { instance, accounts, inProgress } = useMsal();
        const [accessToken, setAccessToken] = useState(null);
        const [graphData, setGraphData] = useState(null);
    
        console.log('log not displayed in console')

        const request = {
            ...loginRequest,
            account: accounts[0]
        };

        // Silently acquires an access token which is then attached to a request for Microsoft Graph data
        instance.acquireTokenSilent(request).then((response) => {
            console.log('acquireTokenSilent')
            setAccessToken(response.accessToken);
            callMsGraph(response.accessToken, start, end).then(
            response => {
                console.log('microsoft response '   response)
            }
            );
        }).catch((e) => {
            console.log('microsoft response error '   e)
            instance.acquireTokenPopup(request).then((response) => {
                setAccessToken(response.accessToken);
                callMsGraph(response.accessToken, start, end).then(
                response => {
                    console.log('microsoft response '   response)
                }
                );
            });
        });

        async function callMsGraph(accessToken, start, end) {
            console.log('callMsGraph ')
        const headers = new Headers();
        const bearer = `Bearer ${accessToken}`;
        
        headers.append("Authorization", bearer);
        console.log('Authorization '   bearer)
    
        const options = {
            method: "GET",
            headers: headers
        };
    
        return fetch(graphConfig.graphCalendarsEndpoint 
             '?startDateTime=' 
             start 
             'amp;endDateTime=' 
             end,
           options)
            .then(response => {
                console.log('microsoft response '   response.json())
                response.json();
            })
            .catch(error => console.log(error));
        }
    }
 

Я не получаю никаких ошибок, вызов api не выполняется, разница между двумя вызовами в том, что один выполняется после нажатия кнопки, а другой при загрузке.

Добавление журналов показало мне, что проблема может быть в этой строке, так как журналы не отображаются после нее:

 const { instance, accounts, inProgress } = useMsal();
 

Что я делаю не так?

Комментарии:

1. добавление попытки/перехвата вокруг const { экземпляр, учетные записи, InProgress } = useMsal(); выдал эту ошибку: Ошибка: Недопустимый вызов крючка. Крючки могут вызываться только внутри тела функционального компонента. Не уверен, почему он выдает эту ошибку, когда она вызывается внутри функции..

Ответ №1:

В events.jsx событиях компонент является компонентом класса, и вы вызываете useMsal() и useState() подключаетесь getMicrosoftEvents . Это не сработает, потому что крючки можно вызывать только в компонентах функций.

Вам нужно сделать компонент событий функциональным, как ImportContacts .

Вместо

 class Events extends Component {
...
 

Сделай это

 const Events= (props) => {
    const { instance, accounts, inProgress } = useMsal();
    const [accessToken, setAccessToken] = useState(null);
    const [graphData, setGraphData] = useState(null);
...
 

Комментарии:

1. Я попробую это сделать, тх