-
Notifications
You must be signed in to change notification settings - Fork 20
[노현지] Sprint6 #66
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
[노현지] Sprint6 #66
The head ref may contain hidden characters: "React-\uB178\uD604\uC9C0-sprint6"
Conversation
|
스프리트 미션 하시느라 수고 많으셨어요. |
스프린트 미션 7 전에 컴포넌트 분리 시도해보겠습니다.크으 좋습니다 ! 리팩토링 해보시면 좋은 경험이 되실거예요 😊 |
| function App() { | ||
| const location = useLocation(); | ||
|
|
||
| return ( | ||
| <> | ||
| {!["/signin", "/signup"].includes(location.pathname) && ( | ||
| <Header className={styles.nav} /> | ||
| )} | ||
| <div className={styles.body}> | ||
| <Outlet /> | ||
| </div> | ||
| {["/"].includes(location.pathname) && ( | ||
| <Footer className={styles.footer} /> | ||
| )} | ||
| </> | ||
| ); | ||
| } |
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.
(제안/선택) 별칭을 사용하면 가독성을 향상시킬 수 있습니다 😊😊
| function App() { | |
| const location = useLocation(); | |
| return ( | |
| <> | |
| {!["/signin", "/signup"].includes(location.pathname) && ( | |
| <Header className={styles.nav} /> | |
| )} | |
| <div className={styles.body}> | |
| <Outlet /> | |
| </div> | |
| {["/"].includes(location.pathname) && ( | |
| <Footer className={styles.footer} /> | |
| )} | |
| </> | |
| ); | |
| } | |
| function App() { | |
| const location = useLocation(); | |
| const isAuthPage = ["/signin", "/signup"].includes(location.pathname); | |
| const isHomePage = location.pathname === "/"; | |
| return ( | |
| <> | |
| {!isAuthPage && <Header className={styles.nav} />} | |
| <div className={styles.body}> | |
| <Outlet /> | |
| </div> | |
| {isHomePage && <Footer className={styles.footer} />} | |
| </> | |
| ); | |
| } |
인라인 조건문을 변수로 추출하면 코드의 의도가 명확해지고 유지보수가 쉬워집니다! 이렇게 하면 가독성이 좋아지고, 새로운 경로가 추가될 때도 쉽게 관리할 수 있어요. 🚀
| function useWindowSize() { | ||
| const [windowSize, setWindowSize] = useState({ | ||
| width: window.innerWidth, | ||
| height: window.innerHeight, | ||
| }); | ||
|
|
||
| useEffect(() => { | ||
| const handleResize = debounce(() => { | ||
| setWindowSize({ | ||
| width: window.innerWidth, | ||
| height: window.innerHeight, | ||
| }); | ||
| }, 300); | ||
|
|
||
| window.addEventListener("resize", handleResize); | ||
| return () => { | ||
| window.removeEventListener("resize", handleResize); | ||
| }; | ||
| }, []); | ||
|
|
||
| return windowSize; | ||
| } |
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.
300이란 값을 파라메터로 받아볼 수 있어요 !:
크으 ~ 커스텀 훅으로 만드셨군요 ! 👍👍👍
| function useWindowSize() { | |
| const [windowSize, setWindowSize] = useState({ | |
| width: window.innerWidth, | |
| height: window.innerHeight, | |
| }); | |
| useEffect(() => { | |
| const handleResize = debounce(() => { | |
| setWindowSize({ | |
| width: window.innerWidth, | |
| height: window.innerHeight, | |
| }); | |
| }, 300); | |
| window.addEventListener("resize", handleResize); | |
| return () => { | |
| window.removeEventListener("resize", handleResize); | |
| }; | |
| }, []); | |
| return windowSize; | |
| } | |
| function useWindowSize(delay = 300) { | |
| const [windowSize, setWindowSize] = useState({ | |
| width: window.innerWidth, | |
| height: window.innerHeight, | |
| }); | |
| useEffect(() => { | |
| const handleResize = debounce(() => { | |
| setWindowSize({ | |
| width: window.innerWidth, | |
| height: window.innerHeight, | |
| }); | |
| }, delay); | |
| window.addEventListener("resize", handleResize); | |
| return () => { | |
| window.removeEventListener("resize", handleResize); | |
| }; | |
| }, []); | |
| return windowSize; | |
| } |
| import { useState, useEffect } from "react"; | ||
| import debounce from "lodash.debounce"; | ||
|
|
||
| function useWindowSize() { |
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.
(제안/심화/의견) debounce도 useDebounce라는 커스텀 훅으로 만들어볼 수도 있을 것 같아요 😊
| const handleLoad = async (query) => { | ||
| try { | ||
| const { list, totalCount } = await getItems(query); | ||
| setItems(list); | ||
| setTotalItemCount(totalCount); | ||
| } catch (error) { | ||
| return; | ||
| } | ||
| }; | ||
|
|
||
| useEffect(() => { | ||
| handleLoad({ page, pageSize, order }); | ||
| }, [page, pageSize, order]); |
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.
handleLoad를 useEffect 안에 선언하는건 어떨까요?
| const handleLoad = async (query) => { | |
| try { | |
| const { list, totalCount } = await getItems(query); | |
| setItems(list); | |
| setTotalItemCount(totalCount); | |
| } catch (error) { | |
| return; | |
| } | |
| }; | |
| useEffect(() => { | |
| handleLoad({ page, pageSize, order }); | |
| }, [page, pageSize, order]); | |
| useEffect(() => { | |
| const handleLoad = async () => { | |
| try { | |
| const { list, totalCount } = await getItems({ page, pageSize, order }); | |
| setItems(list); | |
| setTotalItemCount(totalCount); | |
| } catch (error) { | |
| console.error("아이템을 불러오는 중 오류 발생:", error); | |
| } | |
| }; | |
| handleLoad(); | |
| }, [page, pageSize, order]); | |
handleLoad는 useEffect에서만 사용되는 함수이므로, 굳이 컴포넌트 바깥에 선언할 필요가 없어요 ! useEffect 안에서 선언하면 불필요한 외부 접근을 방지하고, 코드 응집도가 높아져 관리가 쉬워집니다. 😊
| } catch (error) { | ||
| return; | ||
| } |
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.
오류가 발생했음을 알려주는 건 어떨까요? 😊
| } catch (error) { | |
| return; | |
| } | |
| } catch (error) { | |
| alert(error.message); | |
| console.error('ERROR: ', error); | |
| } |
|
|
||
| function AllItems() { | ||
| const [order, setOrder] = useState("recent"); | ||
| const [page, setPage] = useState(1); | ||
| const [pageSize, setPageSize] = useState(10); | ||
| const [isOpen, setIsOpen] = useState(false); | ||
| const [totalItemCount, setTotalItemCount] = useState(0); | ||
| const [pageBound, setPageBound] = useState(0); | ||
| const [items, setItems] = useState([]); | ||
| const MaxPageBound = Math.floor(totalItemCount / pageSize / 5); | ||
| const pageArr = [1, 2, 3, 4, 5]; |
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.
pageArr 컴포넌트의 자원을 사용하지 않기에 상수로 표현할 수 있으며 컴포넌트 바깥에 선언하실 수 있습니다 !
| function AllItems() { | |
| const [order, setOrder] = useState("recent"); | |
| const [page, setPage] = useState(1); | |
| const [pageSize, setPageSize] = useState(10); | |
| const [isOpen, setIsOpen] = useState(false); | |
| const [totalItemCount, setTotalItemCount] = useState(0); | |
| const [pageBound, setPageBound] = useState(0); | |
| const [items, setItems] = useState([]); | |
| const MaxPageBound = Math.floor(totalItemCount / pageSize / 5); | |
| const pageArr = [1, 2, 3, 4, 5]; | |
| const PAGE_ARRAY = [1, 2, 3, 4, 5]; | |
| function AllItems() { | |
| const [order, setOrder] = useState("recent"); | |
| const [page, setPage] = useState(1); | |
| const [pageSize, setPageSize] = useState(10); | |
| const [isOpen, setIsOpen] = useState(false); | |
| const [totalItemCount, setTotalItemCount] = useState(0); | |
| const [pageBound, setPageBound] = useState(0); | |
| const [items, setItems] = useState([]); | |
| const MaxPageBound = Math.floor(totalItemCount / pageSize / 5); |
pageArr는 컴포넌트 내부 상태, props와 연관이 없으므로 컴포넌트 바깥에 선언해볼 수 있어요. 이렇게 하시면 컴포넌트의 내용들은 컴포넌트의 자원과 관련된 로직들로만 구성되며, 리렌더링에 의한 불필요한 재선언을 방지할 수 있습니다 😊
| if (width > 1200) { | ||
| newPageSize = 10; // PC | ||
| } else if (width > 768) { |
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.
(제안) 1200, 768과 같은 숫자가 많이 보이는군요 !
| if (width > 1200) { | |
| newPageSize = 10; // PC | |
| } else if (width > 768) { | |
| if (width > BREAKPOINTS.DESKTOP) { | |
| newPageSize = 10; // PC | |
| } else if (width > BREAKPOINTS.TABLET) { |
앞으로도 재사용이 많을 것으로 예상되어 유지보수성과 가독성을 위해 상수로 정의해두면 어떨지 제안드려봅니다 !
| <div className={styles.title}>전체 상품</div> | ||
| <div className={styles.menu}> | ||
| <form> | ||
| <img src={SearchIcon} className={styles.searchIcon} alt="검색" /> |
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.
단순 장식용으로 있을 경우 ""로 나타낼 수 있습니다 !
| <img src={SearchIcon} className={styles.searchIcon} alt="검색" /> | |
| <img src={SearchIcon} className={styles.searchIcon} alt="" /> |
장식 이미지는 페이지 콘텐츠에 정보를 추가하지 않습니다. 예를 들어, 이미지에서 제공하는 정보는 인접한 텍스트를 사용하여 이미 제공될 수도 있고, 웹 사이트를 시각적으로 더욱 매력적으로 만들기 위해 이미지가 포함될 수도 있습니다.
이러한 경우 스크린 리더와 같은 보조 기술에서 무시할 수 있도록 null(빈) alt텍스트를 제공해야 합니다( ). alt=""이러한 유형의 이미지에 대한 텍스트 값은 화면 판독기 출력에 청각적 혼란을 추가하거나 주제가 인접한 텍스트의 주제와 다른 경우 사용자의 주의를 산만하게 할 수 있습니다. 속성 을 생략하는 alt것도 옵션이 아닙니다. 속성이 제공되지 않으면 일부 화면 판독기가 이미지의 파일 이름을 대신 알려주기 때문입니다.
|
현지님 ! 수고하셨습니다 😊 미션 수행하시느라 정말 고생 많으셨습니다 현지님 😊😊 |
요구사항
기본
상품 등록
심화
상품 등록
주요 변경사항
멘토에게