Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[김창민] week20 #1076

Open
wants to merge 10 commits into
base: part3-김창민
Choose a base branch
from
Open
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { useGetFolders } from "@/src/folder/data-access-folder";
import { useGetLinks } from "@/src/link/data-access-link";
import { useGetFolders, useGetLinks } from "@/src/auth/data-access-auth/api";
import { Layout } from "@/src/sharing/feature-layout";
import { FolderLayout } from "@/src/page-layout/FolderLayout";
import { FolderToolBar } from "@/src/folder/feature-folder-tool-bar";
Expand All @@ -21,9 +20,13 @@ const FolderPage = () => {
}
return undefined;
}, [router.isReady, folderId]);

const { data: folders } = useGetFolders();
const { data: links, loading } = useGetLinks(currentFolderId);
const { searchValue, handleChange, handleCloseClick, result } = useSearchLink(links);
const { data: links, isLoading } = useGetLinks();

const { searchValue, handleChange, handleCloseClick, result } =
useSearchLink(links);

const { ref, isIntersecting } = useIntersectionObserver<HTMLDivElement>();

useEffect(() => {
Expand All @@ -38,10 +41,16 @@ const FolderPage = () => {
<FolderLayout
linkForm={<LinkForm hideFixedLinkForm={isIntersecting} />}
searchBar={
<SearchBar value={searchValue} onChange={handleChange} onCloseClick={handleCloseClick} />
<SearchBar
value={searchValue}
onChange={handleChange}
onCloseClick={handleCloseClick}
/>
}
folderToolBar={
<FolderToolBar folders={folders} selectedFolderId={currentFolderId} />
}
folderToolBar={<FolderToolBar folders={folders} selectedFolderId={currentFolderId} />}
cardList={loading ? null : <CardList links={result} />}
cardList={isLoading ? null : <CardList links={result} />}
/>
</Layout>
);
Expand Down
24 changes: 10 additions & 14 deletions 1-weekly-mission-week15-main/pages/shared/[folderId]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import {
useGetFolder,
useGetSampleFolder,
} from "@/src/folder/data-access-folder";
useGetFolders,
useGetUser,
useGetSharedLinks,
} from "@/src/auth/data-access-auth/api";
import { Layout } from "@/src/sharing/feature-layout";
import { SharedLayout } from "@/src/page-layout/SharedLayout";
import { CardList } from "@/src/link/ui-card-list";
import { FolderInfo } from "@/src/folder/ui-folder-info";
import { ReadOnlyCard } from "@/src/link/ui-read-only-card";
import { SearchBar } from "@/src/link/ui-search-bar";
import { useSearchLink } from "@/src/link/util-search-link/useSearchLink";
import { useRouter } from "next/router";
import { useGetUser } from "@/src/user/data-access-user/useGetUser";
import { useGetSharedLinks } from "@/src/link/data-access-link";

const SharedPage = () => {
const router = useRouter();
const { folderId } = router.query;
const { data: folder } = useGetFolder(folderId as string);
const { data: owner } = useGetUser(folder.userId);
const { data: links } = useGetSharedLinks(folder.userId, folderId as string);
const { data: folder } = useGetFolders();
const { data: owner } = useGetUser();
const { data: links } = useGetSharedLinks();

const { searchValue, handleChange, handleCloseClick, result } =
useSearchLink(links);
Expand All @@ -28,9 +24,9 @@ const SharedPage = () => {
<SharedLayout
folderInfo={
<FolderInfo
profileImage={owner.imageSource}
ownerName={owner.name}
folderName={folder.name}
profileImage={owner?.imageSource}
ownerName={owner?.name}
folderName={folder?.name}
/>
}
searchBar={
Expand Down
164 changes: 164 additions & 0 deletions 1-weekly-mission-week15-main/src/auth/data-access-auth/api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { useQuery, useMutation } from "@tanstack/react-query";
import { useState, useEffect } from "react";
import { Link } from "@/src/link/type";

const BASE_URL = "https://bootcamp-api.codeit.kr/api/linkbrary/v1";
const DEFAULT_USER = {
id: 0,
name: "",
email: "",
imageSource: "",
};

interface LoginParams {
email: string;
password: string;
}

interface SignUpParams extends LoginParams {}

export function usePostLogin() {
return useMutation({
mutationFn: async ({ email, password }: LoginParams) => {
const response = await fetch(`${BASE_URL}/auth/sign-in`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email, password }),
});
const data = await response.json();

if (data?.accessToken) {
localStorage.setItem("accessToken", data.accessToken);
}
return data;
},
});
}

export function usePostSignup() {
return useMutation({
mutationFn: async ({ email, password }: SignUpParams) => {
const response = await fetch(`${BASE_URL}/auth/sign-up`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ email, password }),
});
const data = await response.json();
return data;
},
});
}

export function useGetUser() {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

템플릿 코드에서 중요한차이가 userId를 인자로 받는지 여부군요.
use get user 기 때문에, 특정 user를 조회하는 기능을 가진 훅인데, userId를 받지 않는 다는 것만으로도 혼동을 줄만한 상황입니다. 템플릿코드를 참고해주세요. 아래라인에서 좀더 코멘트드릴게요

const [token, setToken] = useState<string | null>(null);

useEffect(() => {
setToken(localStorage.getItem("accessToken"));
}, []);

return useQuery({
queryKey: ["userInfo"],
queryFn: async () => {
const response = await fetch(`${BASE_URL}/users`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
const responseData = await response.json();

const data = responseData?.[0] && {
id: responseData?.[0].id,
name: responseData?.[0].name,
email: responseData?.[0].email,
imageSource: responseData?.[0].image_source,
};
localStorage.setItem("userId", data.id);

return data;
},
enabled: !!token,
Comment on lines +75 to +85
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

기존 코드에서처럼, !!userId가 추가되어야 react-query로 안정적으로 마이그레이션했다고 할 수 있을거같아요. 지금은 동작이 달라질걸로 보입니다. userId 없이 유저목록을 조회하고 그 중에 언제나 첫번째 유저를 반환할거라서요

enabled: !!token && !!userId

initialData: DEFAULT_USER,
});
}

export function useGetFolders() {
const [token, setToken] = useState<string | null>(null);

useEffect(() => {
setToken(localStorage.getItem("accessToken"));
}, []);

return useQuery({
queryKey: ["folders"],
queryFn: async () => {
const response = await fetch(`${BASE_URL}/folders`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
const data = await response.json();
localStorage.setItem("folderId", data?.[0].id);

return data;
},
enabled: !!token,
});
}
export function useGetLinks() {
const [token, setToken] = useState<string | null>(null);

useEffect(() => {
setToken(localStorage.getItem("accessToken"));
}, []);

return useQuery({
queryKey: ["links"],
queryFn: async () => {
const response = await fetch(`${BASE_URL}/sample/links`, {
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
});
const data = await response.json();
return data;
},
});
}

export function useGetSharedLinks() {
const [userId, setUserId] = useState<number | null>(null);
const [folderId, setFolderId] = useState<number | null>(null);

useEffect(() => {
setUserId(Number(localStorage.getItem("userId")));
setFolderId(Number(localStorage.getItem("folderId")));
}, []);

return useQuery<Link[]>({
queryKey: ["userLinks"],
queryFn: async () => {
const response = await fetch(
`${BASE_URL}/users/${userId}/links?folderId=${folderId}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
},
}
);
const data = await response.json();
return data;
},
enabled: !!userId,
});
}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Input } from "@/src/sharing/ui-input";
import { PasswordInput } from "@/src/sharing/ui-password-input";
import { Controller, useForm } from "react-hook-form";
import { useSignIn } from "../data-access-auth";
import { usePostLogin } from "../data-access-auth/api";
import { ERROR_MESSAGE, PLACEHOLDER } from "./constant";
import { useEffect } from "react";
import styles from "./SignInForm.module.scss";
Expand All @@ -16,30 +16,38 @@ export const SignInForm = () => {
defaultValues: { email: "", password: "" },
mode: "onBlur",
});
const { execute, data, error } = useSignIn({
email: watch("email"),
password: watch("password"),
});
const { mutate: signIn, data, error } = usePostLogin();

useTokenRedirect(data?.data.accessToken);
useTokenRedirect(data?.data?.accessToken);

useEffect(() => {
if (error) {
setError("email", { type: "invalid", message: ERROR_MESSAGE.emailCheck });
setError("password", { type: "invalid", message: ERROR_MESSAGE.passwordCheck });
setError("password", {
type: "invalid",
message: ERROR_MESSAGE.passwordCheck,
});
}
}, [error, setError]);

return (
<form className={cx("form")} onSubmit={handleSubmit(execute)}>
<form
className={cx("form")}
onSubmit={handleSubmit((formData) =>
signIn({ email: formData.email, password: formData.password })
)}
>
<div className={cx("input-box")}>
<label className={cx("label")}>이메일</label>
<Controller
control={control}
name="email"
rules={{
required: ERROR_MESSAGE.emailRequired,
pattern: { value: /\S+@\S+\.\S+/, message: ERROR_MESSAGE.emailInvalid },
pattern: {
value: /\S+@\S+\.\S+/,
message: ERROR_MESSAGE.emailInvalid,
},
}}
render={({ field, fieldState }) => (
<Input
Expand Down
Loading