-
728x90
추가되는 게시글은 순차적으로 커지는 id값을 가지고있어 기존 old순서에서 최신순 배치로 변경하는데 id값을 이용할 수 있었다.
sorting의 순서를 바꾸는건 처음해보는데 useState를 이용한 로직은 머릿속에 금방 그려졌고, 다른 방법도 고민해보고싶어서 찾아보다가 조금 더 복잡한 데이터를 다룰 때 useReducer를 이용한다는 것을 알게되었다. 최신순으로 정렬하는건 useState와 쿼리스트링으로 충분히 구현이 가능했고, useReducer를 사용하는게 과연 더 편할지 직접 로직을 짜보면서 공부해보았다.
useState를 이용한 코드. (sort메소드)
const WikiPage = () => { ... //postData 데이터 원본을 담을 변수 const [postData, setPostData] = useState([]); //posts는 데이터를 정렬해서 담을 변수 const [posts, setPosts] = useState([]); ... //postData에 저장된 요소들의 순서를 바꾸는 부분. useEffect(() => { if (postData) { //sort()메서드를 이용해 b의 id에서 a의 id를 뺀 결과가 음수면 b를 a보다 우선시하고, //결과가 양수면 a를 b보다 우선시한다. 이를 통해 배열을 내림차순으로 정렬할 수 있다. const sortedData = [...postData].sort((a, b) => b.id - a.id); setPosts(sortedData); } }, [postData]); ... return ( <div> //생략 {db && posts.map((a, i) => ( ...
sort()메서드를 이용하는데,
postData에 서버에서 데이터를 받는 그대로를 담고, postData를 복사해서 최신순으로 순서를 바꿔서 sortedData 로 저장한 다음, post에 sortedData를 담는다.
변수가 너무 많아져서 이게 맞나싶었지만,
원본데이터와 정렬된 데이터를 각각 저장함으로써 코드의 유지보수성이 높아진다.
그리고 html로 표현하는 부분에서도 물론 정렬된 데이터가 담기는 posts로 map을 돌린다.
useReducer를 이용한 코드. (쿼리스트링)
나는 useReducer를 처음 이용해보는거라그런지 많이 복잡하게 느껴졌다.
아래 코드에서는 useReducer의 액션 역할이 데이터를 변경or필터링하는데 사용될 뿐이지, 최신순으로 배열을 정렬하는데에는 useReducer가 쓰이지 않는다.
아래코드에서 최신순으로 정렬하는 부분은 axios.get()메소드 url에 _sort=id&_order=desc 쿼리스트링을 추가한 부분이 다했다.
이렇게하면 서버에서 데이터를 가져올 때 id 값을 역순으로 정렬하여 최신순으로 데이터를 가져올 수 있고, 현재 내 서버는 id가 점점 커지는 구조이기때문에 id역순=최신순이다.
const initialState = { postData: [], // 초기값으로 빈 배열을 가지는 postData 속성을 가진 상태 }; const reducer = (state, action) => { switch (action.type) { case "SET_POST_DATA": // SET_POST_DATA 액션 발생 시 기존 상태를 복사하고, 새로운 postData 값을 가진 상태로 반환 return { ...state, postData: action.payload }; default: // 정의되지 않은 액션 타입이 들어온 경우, 기존 상태 그대로 반환 return state; } }; const WikiPage = () => { const navigate = useNavigate(); const [state, dispatch] = useReducer(reducer, initialState); const { postData } = state; useEffect(() => { const getData = async () => { const { data } = await axios.get("http://localhost:3001/post?_sort=id&_order=desc"); dispatch({ type: "SET_POST_DATA", payload: data }); // SET_POST_DATA 액션을 dispatch하여 postData 값을 업데이트 }; getData(); }, []); const [currentPage, setCurrentPage] = useState(1); const itemsPerPage = 5; const totalItemsCount = postData.length; const pageCount = Math.ceil(totalItemsCount / itemsPerPage); const handlePageChange = (e, pageNumber) => { setCurrentPage(pageNumber); }; return ( <> <STitleSpan>Global Knowledge Wiki</STitleSpan> <SAddPost onClick={() => navigate("/newpost")}> <SPencilIcon src={pencil} alt="pencil" /> 새로운 위키 작성하기 </SAddPost> <SListBox> <S1stRow> <STitle>제목</STitle> <SDate>작성일</SDate> </S1stRow> {postData.slice((currentPage - 1) * itemsPerPage, currentPage * itemsPerPage).map((post) => ( <SContentContainer key={post.id} onClick={() => navigate(`/detail/${post.id}`)}> <SContentTitle>{post.title}</SContentTitle> <SContentDate>{post.date}</SContentDate> </SContentContainer> ))}
useReducer를 사용하면 state의 업데이트 로직을 reducer 함수에서 처리하기때문에 상태 업데이트 로직과 관련된 코드가 컴포넌트와 분리되어 있다. 이렇게 분리되어있으면 코드의 가독성이 좋아지고, 상태 관리 로직이 복잡해져도 유지보수가 용이해진다.
useReducer를 사용하여 state와 dispatch 함수를 생성하고,
useEffect로 컴포넌트가 마운트되자마자 서버에서 데이터를 가져와 SET_POST_DATA 액션을 dispatch하여 postData 값을 업데이트한다.
SET_POST_DATA는 데이터를 받아와서 postData 상태를 업데이트하는 액션이다. 이 액션은 reducer 함수 내에서 dispatch 함수를 호출하여 실행된다.
해당 기능구현부분은 상태가 비교적 단순하고 독립적이기 때문에 리덕스나 contextAPI없이 useState만을 사용하여 가볍고 간단하게 구현하는것이 낫다고 생각했다.728x90'Java Script & Type Script' 카테고리의 다른 글
[JS] 내가 몰랐던 ES6 최신문법 (0) 2023.07.10 [React] Recoil 설정과 대표 기능 소개 (0) 2023.04.29 [Refactor] Gnims 코드 리팩토링 with Chat GPT (0) 2023.03.22 [React] 다섯종류의 조건부 렌더링 (0) 2023.03.21 [React] 리덕스 초기 세팅, 리듀서만들기 복습 (0) 2023.03.21