-
Notifications
You must be signed in to change notification settings - Fork 37
[김승석] Sprint8 #287
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
The head ref may contain hidden characters: "React-\uAE40\uC2B9\uC11D-sprint8"
[김승석] Sprint8 #287
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,23 +5,28 @@ import useApi from "./../hooks/useApi"; | |
| import ProfileBox from "./ProfileBox"; | ||
| import CommentEmpty from "./../assets/comment_empty.png"; | ||
| import useOutSideClick from "../hooks/useOutSideClick"; | ||
| import Comment from "../types/Comment"; | ||
|
|
||
| const DetailBtm = ({ id }) => { | ||
| const [commentMenu, setCommentMenu] = useState(null); | ||
| interface Props { | ||
| id?: string; | ||
| } | ||
|
|
||
| const DetailBtm = ({ id }: Props) => { | ||
| const [commentMenu, setCommentMenu] = useState<Props | null>(null); | ||
| const [textValue, setTextValue] = useState(""); | ||
|
|
||
| const handleTextChange = (e) => { | ||
| const handleTextChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => { | ||
| setTextValue(e.target.value); | ||
| }; | ||
|
|
||
| const handleCommentMenu = (id) => { | ||
| const handleCommentMenu = (id: Props) => { | ||
| setCommentMenu((prev) => (prev === id ? null : id)); | ||
| }; | ||
|
|
||
| const menuRef = useRef(null); | ||
| useOutSideClick(menuRef, () => setCommentMenu(null)); | ||
|
|
||
| const { data, loading, error } = useApi(`${id}/comments?limit=10`); | ||
| const { data, loading, error } = useApi<Comment>(`${id}/comments?limit=10`); | ||
|
|
||
| if (loading) { | ||
| return <div>Loading...</div>; | ||
|
|
@@ -49,19 +54,20 @@ const DetailBtm = ({ id }) => { | |
| </button> | ||
| </div> | ||
| <ul className="comment_list"> | ||
| {data.list.length <= 0 ? ( | ||
| {data?.list?.length === 0 ? ( | ||
| <div className="comment_empty"> | ||
| <div className="thum"> | ||
| <img src={CommentEmpty} alt="아직 문의가 없어요 이미지" /> | ||
| </div> | ||
| <p>아직 문의가 없어요</p> | ||
| </div> | ||
| ) : ( | ||
| data.list.map((el) => { | ||
| data?.list.map((el) => { | ||
| return ( | ||
| <li key={el.id}> | ||
| <div className="comment_menu"> | ||
| <button type="button" className="btn_reset" data-menu="button" onClick={() => handleCommentMenu(el.id)}> | ||
| <button type="button" className="btn_reset" data-menu="button" onClick={() => handleCommentMenu(el.id as any)}> | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 해당 버튼은 메뉴가 숨겨져있는 토글버튼인데,
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Props 타입은 const handleCommentMenu = (id: Props) => {
setCommentMenu((prev) => (prev === id ? null : id));
};이 함수부터가 잘못된거같은데요? 함수에서는 id파라미터를 마치 string타입처럼 사용하고있잖아요 const [commentMenu, setCommentMenu] = useState<Props | null>(null);상태의 사용도 마찬가지구요 이건 다시한번 체크해보셔야할것 같네요 |
||
| {/* 질문하기 <button type="button" className="btn_reset" data-menu="button" onClick={() => handleCommentMenu({ id: String(el.id) })}> */} | ||
| <img src={menuIcon} alt="댓글 옵션 열고닫기" /> | ||
| </button> | ||
| {commentMenu === el.id && ( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,9 +3,18 @@ import productImg from "./../assets/item.png"; | |
| import wishIcon from "./../assets/icon_wish.svg"; | ||
| import useApi from "./../hooks/useApi"; | ||
| import ProfileBox from "./ProfileBox"; | ||
| import Product from "../types/Product"; | ||
|
|
||
| const DetailTop = ({ id }) => { | ||
| const { data, loading, error } = useApi(`${id}`); | ||
| interface ProductDetail extends Product { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| isFavorite: boolean; | ||
| } | ||
|
|
||
| interface Props { | ||
| id?: string; | ||
| } | ||
|
|
||
| const DetailTop = ({ id }: Props) => { | ||
| const { data, loading, error } = useApi<ProductDetail>(`${id}`); | ||
|
|
||
| if (loading) { | ||
| return <div>Loading...</div>; | ||
|
|
@@ -22,7 +31,7 @@ const DetailTop = ({ id }) => { | |
| return ( | ||
| <div className="product_detail_item"> | ||
| <div className="thum"> | ||
| <img src={data.images && data.images[0] ? data.images[0] : productImg} alt={data.name} onError={(e) => (e.target.src = productImg)} /> | ||
| <img src={data.images && data.images[0] ? data.images[0] : productImg} alt={data.name} onError={(e) => ((e.target as HTMLImageElement).src = productImg)} /> | ||
| </div> | ||
| <div className="content"> | ||
| <div className="tit">{data.name}</div> | ||
|
|
@@ -44,7 +53,7 @@ const DetailTop = ({ id }) => { | |
|
|
||
| <button className="btn_reset wish_area"> | ||
| <div className="icon"> | ||
| <img src={wishIcon} alt="" /> | ||
| <img src={wishIcon} alt="좋아요 버튼" /> | ||
| </div> | ||
| <div className="numb">{data.favoriteCount}</div> | ||
| </button> | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,22 @@ | ||
| import React, { useEffect, useState } from "react"; | ||
| import axios from "axios"; | ||
| import axios, { AxiosError } from "axios"; | ||
|
|
||
| // axios 인스턴스 생성 | ||
| const api = axios.create({ | ||
| baseURL: "https://panda-market-api.vercel.app/products/", | ||
| }); | ||
|
|
||
| const useApi = (url) => { | ||
| const [data, setData] = useState(null); | ||
| const useApi = <T,>(url: string) => { | ||
| const [data, setData] = useState<T | null>(null); | ||
|
|
||
| const [loading, setLoading] = useState(true); | ||
| const [error, setError] = useState(null); | ||
| const [error, setError] = useState<AxiosError | null>(null); | ||
| useEffect(() => { | ||
| const fetchProduct = async () => { | ||
| try { | ||
| const response = await api.get(url); | ||
| const response = await api.get<T>(url); | ||
| setData(response.data); | ||
| } catch (error) { | ||
| setError(error); | ||
| setError(error as AxiosError); | ||
| } finally { | ||
| setLoading(false); | ||
| } | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍👍👍👍 |
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| export default interface Comment { | ||
| nextCursor: number; | ||
| list: { | ||
| writer: { | ||
| image: string; | ||
| nickname: string; | ||
| id: number; | ||
| }; | ||
| updatedAt: Date; | ||
| createdAt: Date; | ||
| content: string; | ||
| id: number; | ||
| }[]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이렇게 바꿔야하지 않을까요? 확신할 순 없는데
아래에서 해당 상태를 사용하는걸 보면 id값과 비교하는데 사용하네요