[ PART 9 ] GraphQL, Typescript 및 React로 Twitter 복제본 만들기( isLiked? )
12425 단어 showdevgraphqlcareerjavascript
참고로 저는 주로 GraphQL에 대해 배우기 위해 이 챌린지를 시도합니다 ;): Tweeter challenge
Db diagram
이 게시물에서는 연결된 사용자가 피드의 트윗을 이미 좋아했는지 확인하는 방법을 알아봅니다. 이 기능을 구현하는 동안 몇 가지 "문제"가 있었고 작동하더라도 동일한 결과를 얻을 수 있는 더 나은 옵션이 있는지 궁금합니다. 더 나은 방법을 알고 있다면 어떻게 할 수 있었는지 자유롭게 공유하십시오.
우선 트윗 엔터티에 isLiked 필드를 추가해 보겠습니다.
@Field()
isLiked: boolean
데이터 로더를 만들어야 한다는 것을 알고 있지만 이 경우 사용자가 트윗을 좋아하는지 확인하려면 연결된 사용자에 대해 알아야 합니다. 사용자가 필요한 경우 @FieldResolver()에 @Authorized() 주석도 추가해야 함을 의미합니다. 처음에 이 애플리케이션을 시작할 때 연결된 사용자만 트윗에 액세스할 수 있기를 바랐습니다.
나는 그 생각을 고수하고 있지만 일부 속성이 반드시 인증 오류를 반환해서는 안 된다는 사실을 어떻게 처리할 수 있는지 알고 싶었습니다. 이것은 내가 생각하는 isLiked 속성의 경우입니다. 사용자가 연결되면 사용자가 이미 이 트윗을 좋아했는지 확인해야 하지만 사용자가 없으면 false를 반환하면 됩니다. 그러나 @Authorized() 주석을 @FieldResolver()에 전달하면 오류가 발생합니다. 다행스럽게도 authChecker 메서드를 사용하면 역할이라는 두 번째 매개 변수를 전달할 수 있습니다. 내 authChecker의 새 버전은 다음과 같습니다.
src/미들웨어/authChecker.ts
import { AuthChecker } from 'type-graphql'
import { MyContext } from '../types/types'
import { extractJwtToken } from '../utils/utils'
import { verify } from 'jsonwebtoken'
import { JWT_SECRET } from '../config/config'
import { AuthenticationError } from 'apollo-server'
export const authChecker: AuthChecker<MyContext, string> = async (
{ root, args, context, info },
roles
) => {
const {
db,
req,
dataloaders: { userDataloader },
} = <MyContext>context
try {
const token = extractJwtToken(req)
const {
data: { id },
}: any = verify(token, JWT_SECRET as string)
const user = await userDataloader.load(id)
if (!user) {
throw new AuthenticationError('User not found')
}
context.userId = user.id
return true
} catch (e) {
if (roles.includes('ANONYMOUS')) {
context.userId = null
return true
}
throw e
}
}
"ANONYMOUS"역할을 허용하면 오류가 발생하지 않도록 try/catch를 수행합니다. 현재 내가 볼 수 있는 유일한 문제는 "TokenExpired"오류가 프런트엔드에서 적절한 작업을 수행하기 위해 오류를 트리거해야 한다는 것입니다. 이 경우를 처리하려면 오류 유형을 확인하는 것으로 충분해야 합니다 ;).
@FieldResolver() 및 데이터 로더는 다음과 같습니다.
src/resolvers/TweetResolver.ts
@FieldResolver(() => Boolean)
@Authorized('ANONYMOUS')
async isLiked(@Root() tweet: Tweet, @Ctx() ctx: MyContext) {
const {
userId,
dataloaders: { isLikedDataloader },
} = ctx
if (!userId) return false
const isLiked = await isLikedDataloader.load({
tweet_id: tweet.id,
user_id: userId,
})
return isLiked !== undefined
}
src/dataloaders/dataloaders.ts
isLikedDataloader: new DataLoader<any, any, unknown>(async (keys) => {
const tweetIds = keys.map((k: any) => k.tweet_id)
const userId = keys[0].user_id
const likes = await db('likes')
.whereIn('tweet_id', tweetIds)
.andWhere('user_id', userId)
return tweetIds.map((id) => likes.find((l) => l.tweet_id === id))
}),
보시다시피 user_id가 필요하므로 "dataloader"의 키에 대한 개체를 전달합니다. 또한 "authChecker"메서드에서 "ANONYMOUS"모드인 경우 userId를 null로 설정했습니다. 따라서 로그인한 사용자가 없으면 false를 직접 반환합니다. 그렇지 않으면 필요한 것을 검색할 수 있도록 "dataloader"에서 작은 쿼리를 만듭니다.).
그리고 연결된 사용자 없이
이것이 제가이 "문제"를 처리 한 방법입니다. 더 나은/확장 가능한 방법이 있다고 확신하고 몇 가지 가능성에 대해 읽기 시작했습니다. 하지만 지금은 내가 만난 문제를 해결하는 것이지 Twitter를 가리는 것이 아닙니다 :D.
좋은 하루 되시고 다음 편에서 뵙겠습니다 ;).
Reference
이 문제에 관하여([ PART 9 ] GraphQL, Typescript 및 React로 Twitter 복제본 만들기( isLiked? )), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/ipscodingchallenge/part-9-creating-a-twitter-clone-with-graphql-typescript-and-react-isliked-5c9g텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)