전 포스트에서 올린 쿼리스트링으로 관리하는 방식은 새로 코드리뷰를 받고나서 대공사를 했다.
코드리뷰받은 내용은
쿼리스트링으로 전환 잘 시도해주신 것 같습니다! 다만 위의 질문주신 사항과 코드상에서 제가 가이드 드릴 부분이 동일해보여서 여기에 정리해서 답변드릴게요 답변내용 참고하셔서 코드 수정해주세요!!
지금 진행하시고 계시는 방법은 필터링을 queryString과 allList state를 모두 다 관리하고 있습니다. 그런데 우리는 queryString을 useLocation이라는 hook을 통해서 가져오고 이값이 state처럼 다뤄지고 있습니다( react-router-dom에서 제공해주는 customHook입니다) state를 사용하는 근본적인 이유를 보자면 state가 변할 때 화면을 re-render 해주기 위함입니다! 그런데 위에는 이미 queryString을 useLocation hook을 통해서 사용하고 있기에 queryString이 변경되면 다시 화면이 re-render 됩니다! 그래서 굳이 allList state와 queryString의 변화를 모두 신경쓰고 관리할 필요가 없습니다! 오히려 이렇게 진행하고 있기에 allList와 queryString의 sync를 맞춰줘야해서 로직이 복잡해지고 인웅님이 지금 고민하고 계신 여러 문제점이 생기게 됩니다
결론적으로 allList state를 없애고, useLocation으로 가져오는 queryString만으로 필터링 조건을 관리하는 식으로 진행해보세요! 필터링 조건이 변화됬을때는 queryString을 변화시키는 식으로 동작해주시면 됩니다!
리뷰 내용대로
state와 쿼리의 변화를 모두 신경쓰고 관리하고 있기에 로직이 복잡해졌던 것이다. 결론은 state를 없애고 쿼리만으로 관리하는 방식을 말씀해주신 건데 어떻게 해야되는지 고민하는데만 6시간정도를 쏟았던 것 같다. 왜냐면 나는 일단 바뀐 쿼리로 useNavigate 해주기 위해서는 state로 관리해줘야 state가 바뀔 때마다 navigate가 된다는 생각이 강하게 자리잡고 있었기 때문이다. 분명 할 수 있는 방법이 있기에 추천해주셨겠지라는 생각으로 집가는 버스에서도 내내 생각하다가 떠오른 방식이 버튼을 누를 때마다 쿼리로 바꿔주는 방식이였다.
하지만 은근히 까다로웠던 부분이 있었는데 기존에 필터링이나 정렬 페이지네이션이 된 경우 바뀐 쿼리에서 추가적으로 필터링,정렬,페이지네이션이 됐을 때 쿼리가 수정돼야 한다는 것이였다. 그렇게 하기 위해서 첫 번째로 useLoaction 훅을 통해 갖고 온 search가 객체
형식으로 관리돼야 한다는 것이였는데 위 코드에서disassembleFactory
라는 커스텀 메소드가 바로 그 역할을 한다.
간단히 로직을 살펴보면 훅을 통해 갖고 온 쿼리가 빈 값이 아니라면
- 물음표 기호 뒤부터 모든 '=' 기호는 ':'로 바꿔주고 스트링 형식으로 된 쿼리를 '&' 기준으로 나뉜 배열로 만들어준다.
- 임시 빈 객체 'tempObj'를 하나 만들어주는데 'special' 같은 경우에는 하나의 key에 여러개의 value가 들어갈 수 있기 때문에 미리 배열로 선언해주었다.
- 1번에서 만든 배열의 수만큼 순환을 해주며 매번 'listName'이라는 변수에 각 리스트를 ':'기준으로 나눈 배열을 넣어준다.
- 만약 'listName[0]' key값이 'special'이라면 배열 안에 value를 넣어주고 아니라면 객체 안에 새로운 key값과 value값을 만들어준다.
- 순환이 끝났다면 객체로 만들어진 'tempObj'를 호출했던 곳으로 return 해준다.
이렇게 객체 형식으로 만들어진 쿼리에다가 추가적으로 발생한 필터링, 정렬, 페이지네이션의 설정값을 객체에 수정 혹은 삽입을 해주었다면 이제 객체를 다시 쿼리로 만들어 줄 일만 남았다. 이 역할은 assembleFactory
라는 커스텀 메소드가 한다.
- 객체를 담는 빈 배열을 가진 'arrAllList' 변수를 만들어준다.
- 파라미터로 받은 객체 'queryObject' 의 key 갯수만큼 순환을 시켜주는데 하나의
key:value
를 기준으로 빈 배열에 [{key:value},{key1:value1}]와 같이 삽입해준다.- 배열안에 key,value로 나뉜 여러 객체가 들어있는 형태에서 value가 빈 값이거나 빈 배열이 있다면 filter메소드로 걸러주고 그 값을 'existArr'에 넣어준다.
- existArr의 객체 수만큼 map을 돌려주며 만약 키 값이 'special'이라면 배열을 한 번 더 map을 돌려주며
special=value,special=value2
꼴로 만들어준다.- 마지막에 join('&') 메소드를 써주며 배열을 하나의 쿼리 형식의 스트링으로 만들어준다.
모든 버튼 동작에 이 두 메소드들이 들어있으며 만들어진 쿼리스트링으로 navigate
한다.
여기까지가 이번 리팩토링의 핵심이다.
이렇게 큰 리팩토링을 두 번정도 하고 나니 할 때는 막막했지만 하고나니 시야가 넓어지고 있다는 기분이 들었다.