Reactjs 如何向apollo添加auth0访问令牌

Reactjs 如何向apollo添加auth0访问令牌,reactjs,apollo,auth0,apollo-client,react-apollo,Reactjs,Apollo,Auth0,Apollo Client,React Apollo,我正在尝试在react js中将授权令牌添加到apollo客户端,以允许用户登录 index.js import React from 'react'; import ReactDOM from 'react-dom'; import { BrowserRouter as Router } from 'react-router-dom'; import { ThemeProvider } from 'react-jss'; import Theme from 'resources/theme';

我正在尝试在react js中将授权令牌添加到apollo客户端,以允许用户登录

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { ThemeProvider } from 'react-jss';
import Theme from 'resources/theme';
import Routes from 'routes';
import './index.css';
import * as serviceWorker from './serviceWorker';
import { Auth0Provider } from "@auth0/auth0-react";
import 'bootstrap/dist/css/bootstrap.min.css';
import ReactNotification from 'react-notifications-component'
import './components/orders/fonts/NotoSansJP-Regular.otf'
import 'react-notifications-component/dist/theme.css'
import { ApolloProvider , ApolloClient, InMemoryCache } from '@apollo/client';
import { useAuth0 } from "@auth0/auth0-react";


const client = new ApolloClient({
uri: process.env.REACT_APP_API_BACK ,
headers: {
  Authorization: `Bearer ${accessToken}` // doesn’t work 
 },
  cache: new InMemoryCache()
});


ReactDOM.render(
     <Auth0Provider
    domain= {process.env.REACT_APP_AUTH0_DOMAIN }
  clientId= {process.env.REACT_APP_AUTH0_CLIENT_ID}
   redirectUri={window.location.origin}
   audience={process.env.REACT_APP_AUTH0_AUDIENCE}
   scope="warehouse"
   
  >
    <ApolloProvider client={client}> 
    <ThemeProvider theme={Theme}>
        <Router>
        <ReactNotification />
            <Routes />
        </Router>
    </ThemeProvider>,
    </ApolloProvider>
      </Auth0Provider>,
    document.getElementById('root')
);

serviceWorker.unregister();
添加以下行:

import { useAuth0 } from "@auth0/auth0-react";
const {  getAccessTokenSilently } = useAuth0();
 const accessToken = await getAccessTokenSilently
但我认为这不能在index.js中实现

获取令牌:

import { useAuth0 } from "@auth0/auth0-react";
const {  getAccessTokenSilently } = useAuth0();
 const accessToken = await getAccessTokenSilently
这是我在文档和谷歌搜索中发现的,但我认为这在我的情况下是无法做到的,大多数教程显示了如何在个人资料页面中获取用户数据(包括令牌),但这不是我想要的


我想将它传递给index.js中的客户机,您需要为其创建专用组件

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { ThemeProvider } from 'react-jss';
import Theme from 'resources/theme';
import Routes from 'routes';
import './index.css';
import * as serviceWorker from './serviceWorker';
import { Auth0Provider } from "@auth0/auth0-react";
import 'bootstrap/dist/css/bootstrap.min.css';
import ReactNotification from 'react-notifications-component'
import './components/orders/fonts/NotoSansJP-Regular.otf'
import 'react-notifications-component/dist/theme.css'
import { ApolloProvider , ApolloClient, InMemoryCache } from '@apollo/client';
import { useAuth0 } from "@auth0/auth0-react";


const client = new ApolloClient({
uri: process.env.REACT_APP_API_BACK ,
headers: {
  Authorization: `Bearer ${accessToken}` // doesn’t work 
 },
  cache: new InMemoryCache()
});


ReactDOM.render(
     <Auth0Provider
    domain= {process.env.REACT_APP_AUTH0_DOMAIN }
  clientId= {process.env.REACT_APP_AUTH0_CLIENT_ID}
   redirectUri={window.location.origin}
   audience={process.env.REACT_APP_AUTH0_AUDIENCE}
   scope="warehouse"
   
  >
    <ApolloProvider client={client}> 
    <ThemeProvider theme={Theme}>
        <Router>
        <ReactNotification />
            <Routes />
        </Router>
    </ThemeProvider>,
    </ApolloProvider>
      </Auth0Provider>,
    document.getElementById('root')
);

serviceWorker.unregister();
函数useToken(){
const{getAccessTokenInquirement}=useAuth0();
const[token,setToken]=useState(null);
useEffect(()=>{getAccessTokenInquirement().then(setToken)},[]
返回令牌;
}
函数提供程序({children}){
const token=useToken();
//useRef而不是UseMoom,以确保不会随机重新创建客户端
const clientRef=useRef(null);
if(令牌和clientRef.current){
//此代码只能执行一次。
clientRef.current=新客户端(/**/)
}
如果(!clientRef.current){
//现在我们必须等到客户机用令牌初始化,所以您可能需要添加一些微调器
返回null;
}
返回

您仍然使用类似的方法:

函数useToken(){/*应返回实际令牌,并在更改时更新它*/}
函数提供程序({children}){
const token=useToken();
const tokenRef=useRef(令牌);
const clientRef=useRef(null);
tokenRef.current=token;//确保tokenRef始终具有最新的token
如果(!clientRef.current){
//此函数在每个请求上单独调用,并从ref获取令牌
const authLink=setContext(({headers})=>{
//与文档示例类似,但您从ref读取令牌
const token=tokenRef.current;
返回{
标题:{
…标题,
授权:`Bearer${token}`,
}
}
});
clientRef.current=新客户端(
链接:authLink.concat(httpLink),
// ...
)
}
}
无论第一种或第二种情况,在
index.js
中的用法:

ReactDOM.render(
{/* ... */}
,
document.getElementById(“根”)
);

这里的主要问题是
MyApolloProvider
应该在
Auth0Provider
中才能访问令牌。

这就是我最后要做的:

import {
  ApolloProvider,
  ApolloClient,
  InMemoryCache,
  HttpLink,
} from '@apollo/client';
import { setContext } from '@apollo/link-context';
import { useAuth0 } from '@auth0/auth0-react';

const ApolloProviderWithAuth0 = ({ children }) => {
  const { getAccessTokenSilently } = useAuth0();

  const httpLink = new HttpLink({
    uri: process.env.REACT_APP_GRAPHQL_URI,
  });

  const authLink = setContext(async (_, { headers, ...rest }) => {
    let token;
    try {
      token = await getAccessTokenSilently();
    } catch (error) {
      console.log(error);
    }

    if (!token) return { headers, ...rest };

    return {
      ...rest,
      headers: {
        ...headers,
        authorization: `Bearer ${token}`,
      },
    };
  });

  const client = React.useRef();

  if (!client.current) {
    client.current = new ApolloClient({
      link: authLink.concat(httpLink),
      cache: new InMemoryCache(),
    });
  }

  return (
    <ApolloProvider client={client.current}>
      {children}
    </ApolloProvider>
  );
};

export { ApolloProviderWithAuth0 };
导入{
阿波罗供应商,
阿波罗客户,
在记忆中,
HttpLink,
}来自“@apollo/client”;
从“@apollo/link-context”导入{setContext};
从'@auth0/auth0'导入{useAuth0};
常量providerWithAuth0=({children})=>{
const{getAccessTokenInquirement}=useAuth0();
const httpLink=新的httpLink({
uri:process.env.REACT\u APP\u GRAPHQL\u uri,
});
const authLink=setContext(异步({headers,…rest})=>{
让代币;
试一试{
token=wait getaccesstokensilent();
}捕获(错误){
console.log(错误);
}
如果(!token)返回{headers,…rest};
返回{
休息
标题:{
…标题,
授权:`Bearer${token}`,
},
};
});
const client=React.useRef();
如果(!client.current){
client.current=新客户端({
链接:authLink.concat(httpLink),
缓存:新的InMemoryCache(),
});
}
返回(
{儿童}
);
};
导出{ApolloProviderWithAuth0};

然后将其用作应用程序组件中的提供者。

在第二个示例中,您能完成代码吗?以及如何在index.Js中使用它?我尝试了相同的方法,但使用不同的代码,出现了cros问题,我认为使用此代码我也会遇到同样的问题