From f8ecaa51b5f7f59243bcb51f3e1557afc4e79afb Mon Sep 17 00:00:00 2001 From: Aaron William Po Date: Sun, 2 Apr 2023 21:51:10 -0400 Subject: [PATCH] Update beer like button to use custom hook to load like status --- components/BeerById/BeerPostLikeButton.tsx | 30 +++---------- hooks/useCheckIfUserLikesBeerPost.ts | 45 +++++++++++++++++++ .../sendCheckIfUserLikesBeerPostRequest.ts | 31 ------------- 3 files changed, 51 insertions(+), 55 deletions(-) create mode 100644 hooks/useCheckIfUserLikesBeerPost.ts delete mode 100644 requests/sendCheckIfUserLikesBeerPostRequest.ts diff --git a/components/BeerById/BeerPostLikeButton.tsx b/components/BeerById/BeerPostLikeButton.tsx index 84b6ae9..4ccf7f2 100644 --- a/components/BeerById/BeerPostLikeButton.tsx +++ b/components/BeerById/BeerPostLikeButton.tsx @@ -1,41 +1,23 @@ -import UserContext from '@/contexts/userContext'; +import useCheckIfUserLikesBeerPost from '@/hooks/useCheckIfUserLikesBeerPost'; import sendLikeRequest from '@/requests/sendLikeRequest'; -import { Dispatch, FC, SetStateAction, useContext, useEffect, useState } from 'react'; +import { Dispatch, FC, SetStateAction, useState } from 'react'; import { FaThumbsUp, FaRegThumbsUp } from 'react-icons/fa'; -import sendCheckIfUserLikesBeerPostRequest from '@/requests/sendCheckIfUserLikesBeerPostRequest'; const BeerPostLikeButton: FC<{ beerPostId: string; setLikeCount: Dispatch>; }> = ({ beerPostId, setLikeCount }) => { - const [loading, setLoading] = useState(true); - const [isLiked, setIsLiked] = useState(false); - - const { user } = useContext(UserContext); - - useEffect(() => { - if (!user) { - setLoading(false); - return; - } - sendCheckIfUserLikesBeerPostRequest(beerPostId) - .then((currentLikeStatus) => { - setIsLiked(currentLikeStatus); - setLoading(false); - }) - .catch(() => { - setLoading(false); - }); - }, [user, beerPostId]); + const { isLiked, mutate: mutateLikeStatus } = useCheckIfUserLikesBeerPost(beerPostId); + const [loading, setLoading] = useState(false); const handleLike = async () => { try { setLoading(true); await sendLikeRequest(beerPostId); - setIsLiked(!isLiked); setLikeCount((prevCount) => prevCount + (isLiked ? -1 : 1)); + mutateLikeStatus(); setLoading(false); - } catch (error) { + } catch (e) { setLoading(false); } }; diff --git a/hooks/useCheckIfUserLikesBeerPost.ts b/hooks/useCheckIfUserLikesBeerPost.ts new file mode 100644 index 0000000..0e01a57 --- /dev/null +++ b/hooks/useCheckIfUserLikesBeerPost.ts @@ -0,0 +1,45 @@ +import UserContext from '@/contexts/userContext'; +import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; +import { useContext } from 'react'; +import useSWR from 'swr'; +import { z } from 'zod'; + +const useCheckIfUserLikesBeerPost = (beerPostId: string) => { + const { user } = useContext(UserContext); + const { data, error, isLoading, mutate } = useSWR( + `/api/beers/${beerPostId}/like/is-liked`, + async () => { + if (!user) { + throw new Error('User is not logged in.'); + } + + const response = await fetch(`/api/beers/${beerPostId}/like/is-liked`); + const json = await response.json(); + const parsed = APIResponseValidationSchema.safeParse(json); + + if (!parsed.success) { + throw new Error('Invalid API response.'); + } + + const { payload } = parsed.data; + const parsedPayload = z.object({ isLiked: z.boolean() }).safeParse(payload); + + if (!parsedPayload.success) { + throw new Error('Invalid API response.'); + } + + const { isLiked } = parsedPayload.data; + + return isLiked; + }, + ); + + return { + isLiked: data, + error: error as unknown, + isLoading, + mutate, + }; +}; + +export default useCheckIfUserLikesBeerPost; diff --git a/requests/sendCheckIfUserLikesBeerPostRequest.ts b/requests/sendCheckIfUserLikesBeerPostRequest.ts deleted file mode 100644 index b815004..0000000 --- a/requests/sendCheckIfUserLikesBeerPostRequest.ts +++ /dev/null @@ -1,31 +0,0 @@ -import APIResponseValidationSchema from '@/validation/APIResponseValidationSchema'; -import { z } from 'zod'; - -const sendCheckIfUserLikesBeerPostRequest = async (beerPostId: string) => { - const response = await fetch(`/api/beers/${beerPostId}/like/is-liked`); - const data = await response.json(); - - const parsed = APIResponseValidationSchema.safeParse(data); - - if (!parsed.success) { - throw new Error('Invalid API response.'); - } - - const { payload } = parsed.data; - - const parsedPayload = z - .object({ - isLiked: z.boolean(), - }) - .safeParse(payload); - - if (!parsedPayload.success) { - throw new Error('Invalid API response.'); - } - - const { isLiked } = parsedPayload.data; - - return isLiked; -}; - -export default sendCheckIfUserLikesBeerPostRequest;