React + MSAL + React Router 6.4.1(最新版本)加载器功能问题

问题描述 投票:0回答:1

亲爱的 React 开发者。

当您想要使用新的加载程序功能时,有人可以解释或展示在当前最新版本 6.4.1 中将 MSAL 与 React Router 结合使用时的最佳方法是什么吗?

基于新的加载程序功能,您可以在此处阅读:

“每个路由都可以定义一个“加载器”函数,以便在渲染之前向路由元素提供数据。”

https://reactrouter.com/en/main/route/loader

我之所以提出这个问题,是因为我缺乏想象力……我记得访问 msal 实例的唯一方法是在 MsalProvider 内的组件上使用 MSAL 库提供的挂钩。但是,新的加载程序功能依赖于一个普通函数,我无法使用挂钩或访问任何应用程序状态。

非常欢迎任何帮助。 预先感谢。

为了在下面提供一些背景信息,我分享了一些我的应用程序代码。

在我的 UserEditScreen.tsx 中:


// UserEditScreen component definition

....

// loader definition outside UserEditScreen component

export const loader = ({ request, params }: LoaderFunctionArgs) => {
...
  // some more code to clarify my need on the msal instance inside the loader
  const request = {
      account: msalInstance.getActiveAccount(),
      scopes: scopes
    }
    const accessToken = await msalInstance.acquireTokenSilent(request)
      .then(response => response.accessToken)
      .catch(error => {        
        console.error(error);
      })
// then with the accessToken I can just use made 
// a javascript fetch request to my secured endpoint in azure

 ...
}

在我的 app.tsx 中

type AppProps = {
  msalInstance: PublicClientApplication;
}

const router = createBrowserRouter(createRoutesFromElements(
  <Route path="/" errorElement={<GlobalError />}>
    ...
    <Route path="/administration" element={
      <AuthenticatedScreen>
        <AdministrationScreen />
      </AuthenticatedScreen>
    }>
      <Route path='users' element={<UsersScreen />} />
      <Route path='users/new' element={<UserNewScreen />} />
      <Route path='users/:id/edit'
        element={<UserEditScreen />}
        loader={userLoader}
        errorElement={<UserEditError />}
      />
    </Route>
    ...
  </Route>

));

function App({ msalInstance }: AppProps) {

  return (
    <MsalProvider instance={msalInstance}>
      <RouterProvider router={router} />
    </MsalProvider>
  );
}

export default App;

在我的index.tsx中

const msalInstance = new PublicClientApplication(msalConfig);
const accounts = msalInstance.getAllAccounts();

if (accounts.length > 0) {
  msalInstance.setActiveAccount(accounts[0]);
}

msalInstance.addEventCallback((event: EventMessage) => {
  if (event.eventType === EventType.LOGIN_SUCCESS && event.payload) {
    const payload = event.payload as AuthenticationResult;
    const account = payload.account;
    msalInstance.setActiveAccount(account);
  }
});

const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);

root.render(
  <React.StrictMode>
    <App msalInstance={msalInstance} />
  </React.StrictMode>
);

reactjs typescript react-router azure-ad-msal
1个回答
5
投票

您可以将其转换为一个函数,该函数将

msalInstance
作为参数以在范围内关闭它并返回配置的路由器,而不是创建路由器组件。

示例:

应用程序

type AppProps = {
  msalInstance: PublicClientApplication;
}

interface CreateRouter {
  msalInstance: PublicClientApplication;
}

const createRouter = ({ msalInstance }: CreateRouter) => createBrowserRouter(
  createRoutesFromElements(
    <Route path="/" errorElement={<GlobalError />}>
      ...
      <Route path="/administration" element={
        <AuthenticatedScreen>
          <AdministrationScreen />
        </AuthenticatedScreen>
      }>
        <Route path='users' element={<UsersScreen />} />
        <Route path='users/new' element={<UserNewScreen />} />
        <Route path='users/:id/edit'
          element={<UserEditScreen />}
          loader={userLoader(msalInstance)}
          errorElement={<UserEditError />}
        />
      </Route>
      ...
    </Route>
  )
);
function App({ msalInstance }: AppProps) {
  const router = React.useMemo(
    () => createRouter({ msalInstance }),
    [msalInstance]
  );

  return (
    <MsalProvider instance={msalInstance}>
      <RouterProvider router={router} />
    </MsalProvider>
  );
}

export default App;

用户编辑屏幕

类似地,

loader
函数可以更新为柯里化函数,该函数将
msalInstance
对象作为参数,并返回加载器函数,其中
msalInstance
对象在范围内关闭。

// loader definition outside UserEditScreen component
export const loader = (msalInstance: PublicClientApplication) => 
  ({ request, params }: LoaderFunctionArgs) => {
    ...
    // some more code to clarify my need on the msal instance inside the loader
    const request = {
      account: msalInstance.getActiveAccount(),
      scopes: scopes
    }
    const accessToken = await msalInstance.acquireTokenSilent(request)
      .then(response => response.accessToken)
      .catch(error => {        
        console.error(error);
      })
    // then with the accessToken I can just use made 
    // a javascript fetch request to my secured endpoint in azure

    ...
  };
© www.soinside.com 2019 - 2024. All rights reserved.