问题描述
我正在使用 Nextjs、Cognito、Amplify Auth、Apollo 客户端和自定义 Graphql 服务器。我的 Cognito 池不是使用 Amplify CLI 创建的。
我成功了
但我没有在 apolloClient.ts 中的 setAuthorizationLink > setContext 中获取 User。它一直说用户未通过身份验证。
感谢任何帮助。
_app.ts
import { ApolloProvider } from '@apollo/client';
import { useApollo } from '../src/lib/Apollo/apolloClient';
import '../styles/globals.css';
import Amplify from 'aws-amplify';
import Navbar from '../src/Container/Navigation';
import { ThemeProvider } from '@emotion/react';
import { theme } from '../src/Components/Theme';
Amplify.configure({
ssr: true,Auth: {
region: 'us-east-1',userPoolId: 'x',userPoolWebClientId: 'y',cookieStorage: {
domain: 'localhost',path: '/',expires: 365,secure: false,},});
export default function App({ Component,pageProps }) {
const apolloClient = useApollo(pageProps);
return (
<ThemeProvider theme={theme}>
<ApolloProvider client={apolloClient}>
<Navbar />
<Component {...pageProps} />
</ApolloProvider>
</ThemeProvider>
);
}
apolloClient.ts
import { useMemo } from 'react';
import {
ApolloClient,ApolloLink,HttpLink,InMemoryCache,normalizedCacheObject,} from '@apollo/client';
import { concatPagination } from '@apollo/client/utilities';
import merge from 'deepmerge';
import isEqual from 'lodash/isEqual';
import { setContext } from '@apollo/client/link/context';
import { Auth } from 'aws-amplify';
export const APOLLO_STATE_PROP_NAME = '__APOLLO_STATE__';
let apolloClient: ApolloClient<normalizedCacheObject>;
// Get Apollo Backend
const apolloBackend = new HttpLink({
uri: 'http://localhost:4000/graphql/',credentials: 'include',});
const authLink = setContext(async (req,prev) => {
// console.log('setContext',req);
// // console.log('setContext',prev);
try {
console.log((await Auth.currentAuthenticatedUser()).getIdToken().payload);
const session = await Auth.currentSession();
const token = session.getAccesstoken();
return {
headers: { Authorization: token },};
} catch (err) {
console.log('authLink',err);
return {
headers: { Authorization: undefined },};
}
});
function createApolloClient() {
return new ApolloClient({
ssrMode: typeof window === 'undefined',link: ApolloLink.from([authLink,apolloBackend]),cache: new InMemoryCache({
typePolicies: {
Query: {
fields: {
allPosts: concatPagination(),}),});
}
export function initializeApollo(initialState = null) {
const _apolloClient = apolloClient ?? createApolloClient();
// If your page has Next.js data fetching methods that use Apollo Client,the initial state
// gets hydrated here
if (initialState) {
// Get existing cache,loaded during client side data fetching
const existingCache = _apolloClient.extract();
// Merge the existing cache into data passed from getStaticProps/getServerSideProps
const data = merge(initialState,existingCache,{
// combine arrays using object equality (like in sets)
arrayMerge: (destinationArray,sourceArray) => [
...sourceArray,...destinationArray.filter((d) =>
sourceArray.every((s) => !isEqual(d,s))
),],});
// Restore the cache with the merged data
_apolloClient.cache.restore(data);
}
// For SSG and SSR always create a new Apollo Client
if (typeof window === 'undefined') return _apolloClient;
// Create the Apollo Client once in the client
if (!apolloClient) apolloClient = _apolloClient;
return _apolloClient;
}
export function addApolloState(client,pageProps) {
if (pageProps?.props) {
pageProps.props[APOLLO_STATE_PROP_NAME] = client.cache.extract();
}
return pageProps;
}
export function useApollo(pageProps) {
const state = pageProps[APOLLO_STATE_PROP_NAME];
const store = useMemo(() => initializeApollo(state),[state]);
return store;
}
我.ts
import { gql } from '@apollo/client';
import { withSSRContext } from 'aws-amplify';
import React from 'react';
import {
addApolloState,initializeApollo,} from '../src/lib/Apollo/apolloClient';
import MeComp from './meComp';
import Amplify from 'aws-amplify';
Amplify.configure({
ssr: true,});
const me = () => {
return <MeComp />;
};
export async function getServerSideProps(context) {
const { Auth } = withSSRContext(context);
const apolloClient = initializeApollo();
const user = await Auth.currentAuthenticatedUser();
// console.log('getServerSideProps',user);
const query = gql`
query {
me {
authenticated
user {
id
}
}
}
`;
await apolloClient.query({
query,});
return addApolloState(apolloClient,{
props: {},// revalidate: 1,});
}
export default me;
Navbar.ts
/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable jsx-a11y/no-static-element-interactions */
import React,{ useEffect,useState } from 'react';
import Link from 'next/link';
import { Auth,Hub } from 'aws-amplify';
import { Container } from 'next/app';
import { Header,SiteNav,MenuToggle,Hamburger } from './style';
import { useRouter } from 'next/router';
const Navbar = () => {
const [open,setopen] = useState(false);
const [user,setUser] = useState(null);
const router = useRouter();
Hub.listen('auth',({ payload: { event,data } }) => {
switch (event) {
case 'signIn':
console.log(1,data);
setUser(data);
break;
case 'signOut':
console.log(2,data);
setUser(undefined);
break;
}
});
useEffect(() => {
// Access the user session on the client
Auth.currentAuthenticatedUser()
.then((user) => {
console.log('User: ',user);
setUser(user);
})
.catch((err) => {
console.log('Error:',err);
setUser(null);
});
},[]);
const authenticated = user ? true : false;
return (
<Header data-test='header'>
<Container>
<SiteNav open={open}>
<ul>
<li data-test='home'>
<Link href='/'>
<a onClick={() => setopen(!open)}>Home</a>
</Link>
</li>
<li data-test='me'>
<Link href='/me'>
<a onClick={() => setopen(!open)}>Me</a>
</Link>
</li>
...
{authenticated ? (
<li data-test='cockpit'>
<Link href='/cockpit'>
<a onClick={() => setopen(!open)}>Cockpit</a>
</Link>
</li>
) : null}
{!authenticated ? (
<li data-test='register'>
<Link href='/auth/register'>
<a onClick={() => setopen(!open)}>Register</a>
</Link>
</li>
) : null}
{!authenticated ? (
<li data-test='login'>
<Link href='/auth/login'>
<a onClick={() => setopen(!open)}>Login</a>
</Link>
</li>
) : null}
{authenticated ? (
<li data-test='logout'>
<a
onClick={async () => {
try {
await Auth.signOut();
setopen(!open);
router.push('/');
} catch {
return;
}
}}
>
logout
</a>
</li>
) : null}
</ul>
</SiteNav>
{authenticated ? <span>{`Logged in as: ${user.username}`}</span> : null}
<MenuToggle onClick={() => setopen(!open)}>
<Hamburger open={open} />
</MenuToggle>
</Container>
</Header>
);
};
export default Navbar;
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)