이번 2차 프로젝트에서 나는 상품 리스트 페이지를 담당했다.
회원가입, 로그인 페이지
메인 페이지
상세 페이지
이번 프로젝트에서는 fetch 대신 axios 를 사용할 기회가 있었다. pagination 을 구현해야 할 상황이 있었는데 여러 자료를 찾아보다 axios 를 적용하게 되었다.
일단 axios 란 http 통신을 하는데 매우 인기있는 js 라이브러리 이며 promise 를 기반으로 하며 async/await 문법을 사용하여 XHR 요청을 매우 쉽게 할 수 있다고 한다.
npm install axios
import React, { useState, useEffect } from "react";
import axios from "axios";
const [currentPage, setCurrentPage] = useState(1);
const [postsPerPage] = useState(16);
// useEffect 에서 백엔드에서 넘겨주는 데이터를 저장
useEffect(() => {
const fetchPosts = async () => {
const res = await axios.get(`${API}/product/list`);
setPosts(res.data.data);
};
fetchPosts();
}, []);
const indexOfLastPost = currentPage * postsPerPage;
const indexOfFirstPost = indexOfLastPost - postsPerPage;
const currentPosts = posts.slice(indexOfFirstPost, indexOfLastPost);
const paginate = (pageNumber) => {
setCurrentPage(pageNumber);
window.scrollTo({ top: 320, behavior: "smooth" });
}
return (
~~~
{
currentPosts.map((post) => (
<Item
key={post.id}
image={posts.image[0]}
hover={
post.image[0] === post.image[1]
? post.image[0]
: post.image[1]
}
hashFirst={posts.tag[0]}
hashSecond={posts.tag[1]}
productName={post.korean_name}
>
))
}
~~~
<Pagination
postsPerPage={postsPerPage}
totalPosts={posts.length}
paginate={paginate}
/>
);
import React, { useState } from "react";
import styled from "styled-components";
function Pagination({ postsPerPage, totalPosts, paginate }) {
const pageNumber = [];
const [activeBtn, setActiveBtn] = useState(1);
for(let i = 1; i <= Math.ceil(totlaPosts / postsPerPage); i++) {
pageNumber.push(i);
}
return (
<PaginationOuter>
{pageNumbers.map((number) => (
<PageBtn
key={number}
onClick={() => {
paginate(number);
setActiveBtn(number);
}}
backgroundColor={activeBtn === number ? "#2b2b2b" : ""}
color={activeBtn === number ? "white" : "#2b2b2b"}
hover={activeBtn === number ? "#4478be" : ""}
>
{number}
</PageBtn>
))}
</PaginationOuter>
);
}
1차 프로젝트 때 다양한 크기의 스크린에서 스크롤 이벤트가 발생했을 때 scrollY 를 사용하지 않고 정확한 타겟으로 스크롤 되는 기능을 구현하기 위해 useRef 라는 것을 사용하면 된다는 것을 알게 되었다. 하지만 개념자체도 이해하기 쉽지 않았고, 적용하기란 더욱 어려운 일이었다.
2차 프로젝트 때에 꼭 적용하고 싶다는 생각을 했다. 1차 때 구현해내지 못한 기능이 똑같이 적용되어져 있는 페이지가 있길래 꼭 useRef 를 사용하여 기능구현을 해보리라 다짐했다. 하지만 시간이 부족해서 그 페이지 자체를 구현하지 못하게 되는 상황이 생겼다.
아쉬워 하던 중 상품 리스트 페이지를 구현하면서 useRef 를 사용할 수 있게 되었다.
import { useRef, useState, useEffect } from "react";
function useHover() {
const [value, setValue] = useState(false);
const ref = useRef(null);
const handleMouseOver = () => setValue(true);
const handleMouseOut = () => setValue(false);
useEffect(() => {
const node = ref.current;
if (node) {
node.addEventListener("mouseover", handleMouseOver);
node.addEventListener("mouseout", handleMouseOut);
return () => {
node.removeEventListener("mouseover", handleMouseOver);
node.removeEventListener("mouseout", handleMouseOut);
};
}
}, []);
return [ref, value];
}
export default useHover;
import React from "react";
import { useHistory } from "react-router-dom";
import styled from "styled-components";
import New from "./New";
import Best from "./Best";
import useHover from "./ItemUseHover";
function Item({
isId,
isNew,
isBest,
image,
hashFirst,
hashSecond,
productName,
hover,
}) {
const [hoverRef, isHoverd] = useHover();
const history = useHistory();
const goToDetail = () => {
history.push(`/product/list/${isId}`);
};
return (
<ItemOuter onClick={goToDetail}>
<ItemImg ref={hoverRef} src={isHoverd ? hover : image} />
<Mark>
{isNew === "true" && <New />}
{isBest === "true" && <Best />}
</Mark>
<HashWrapper>
<HashFirst>{hashFirst}</HashFirst>
<HashSecond>{hashSecond}</HashSecond>
</HashWrapper>
<ProductName>{productName}</ProductName>
</ItemOuter>
);
}
위코드의 마지막 프로젝트가 끝났다. 이 모든 일들이 정말 순식간에 지나갔다. 모두가 서로의 성장을 위해 함께 애썼다. 고생한 팀원들에게 감사하다는 말을 전하고 싶다. 항상 열심히 했지만 아쉬움이 남는다. 1차 프로젝트에 비해 중간중간 새로 배우는 내용들이 많아 적용하는데 시간을 더욱 들여야 했다. redux 의 존재를 알고 필요를 매우 느꼈지만 시간관계상 프로젝트가 우선이었기에 포기해야 했다. 화려하고 멋진 기능들을 가진 페이지를 하나라도 더 구현해보고자 욕심이 앞서 페이지를 선택했지만 결국 시도조차 못한 페이지가 있다.
아쉬움이 남기도 하지만 모르는 부분을 스스로 공부하여 적용시켜 구현해낸 기능들이 나를 뿌듯하게 만들기도 한다. useRef 는 아직 정확하게 이해하진 못했지만 타겟을 지정하여 어떠한 효과를 줄 수 있는 듯하다. pagination 역시 유튜브 동영상을 보고 적용시켰는데 적용시켜보고 기능구현이 되는 것 자체가 신기했고 뿌듯했다. styled-components 는 css 파일을 따로 만들지 않고 곧바로 js 파일에서 스타일 작업을 하는 것, 그리고 props 를 넘길 때도 정말 유용하다는 것을 알게 되었다. 너무 신기하고 더 공부해보고 싶은 것들이 넘친다.
다음주 부터는 기업협업을 나가게 된다. 정말 많이 부족하지만, 배워야 할 것들이 산더미같을 테지만 멘탈관리, 시간관리, 체력관리 정말 잘해서 멋진 과정과 결과를 만들어내고 싶다.