我正在关注 React Authentication By Example:Using React Router 6 [1]。我正在使用以下依赖项:
react-router-dom 6.3.0
react 18.2
auth0-react 2.0.1
一切正常,直到我尝试在 useEffect() 中调用 getAccessTokenSilently() 导致无限循环。我搜索了所有相关主题,但找不到解决方案。
repro 的最小代码片段(严格遵循上面的教程):
Auth0ProviderWithNavigate 实现:
import { Auth0Provider } from '@auth0/auth0-react';
import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
export const Auth0ProviderWithNavigate = ({ children }) => {
const navigate = useNavigate();
const onRedirectCallback = (appState) => {
navigate(appState?.returnTo || window.location.pathname);
};
if (!(domain && clientId && redirectUri)) {
return null;
}
return (
<Auth0Provider
domain={domain}
clientId={clientId}
authorizationParams={{
audience: audience,
redirect_uri: redirectUri
}}
onRedirectCallback={onRedirectCallback}
useRefreshTokens={true}
>
{children}
</Auth0Provider>
);
};
AuthenticationGuard 包含在所有需要身份验证的路由中:
import { withAuthenticationRequired } from '@auth0/auth0-react';
export const AuthenticationGuard = ({ component }) => {
const Component = withAuthenticationRequired(component, {
onRedirecting: () => (
<div className="page-layout">
Loading...
</div>
),
});
return <Component />;
};
index.tsx 实现:
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { BrowserRouter } from 'react-router-dom';
import { Auth0ProviderWithNavigate } from './Auth0Provider';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.Fragment>
<BrowserRouter>
<Auth0ProviderWithNavigate>
<App />
</Auth0ProviderWithNavigate>
</BrowserRouter>
</React.Fragment>
);
reportWebVitals();
App.tsx 在 useEffect() 中检查 getAccessTokenSilently() 后,我也看到它被无限调用:
import * as React from 'react';
import { Routes, Route } from 'react-router-dom';
import Home from 'pages/Home';
import { AuthenticationGuard } from 'components/AuthenticationGuard';
import { AppProvider } from './context';
export default function App(): JSX.Element {
const { isAuthenticated } = useAuth0();
console.log('isAuthenticated: ', isAuthenticated); // <------------ this prints in infinite loop
return (
<React.Fragment>
<AppProvider>
<Routes>
<Route path="/" element={<AuthenticationGuard component={Home} />} />
</Routes>
</div>
</AppProvider>
</React.Fragment>
);
}
AppProvider 实现:
import React, { createContext, useReducer } from 'react';
const AppProvider = ({ children }: ProviderProps) => {
const [state, dispatch] = useReducer(combinedReducers, initialState);
return <AppContext.Provider value={{ state, dispatch }}>{children}</AppContext.Provider>;
};
export { AppProvider };
无限循环发生的Home组件实现:
import * as React from 'react';
import { useEffect } from 'react';
export default function Home(): JSX.Element {
useEffect(() => {
(async () => {
const token = await getAccessTokenSilently({
authorizationParams: {
audience: audience
},
});
console.log('token ', token); // <----------- this prints in infinite loop
})();
}, []);
return (
<div>Hello from app!</div>
);
}
当我调用 getAccessTokenSilently 访问我自己的 api 时,我没有遇到任何问题。它仅在尝试在 useEffect 中使用 getAccessTokenSilently 时发生。
任何关于如何解决这个问题的指示或关于为什么会发生这种情况的想法将不胜感激。非常感谢!