[Main Project] UDog / 구현하기 - 중복 데이터 에러, useLocation

soohyunee·2023년 3월 26일
0

[Main Project] UDog

목록 보기
14/18
post-thumbnail

1. 구현하기

진행 상황

  • 닉네임 변경 유효성 추가
  • 회원탈퇴 로직 변경
  • 미용실 무한 스크롤 버그 수정

진행 예정

  • 화면정의서 정리
  • css 통일화

2. TIL

2-1. 중복 데이터 에러

상태 변화로 인한 중복 데이터

geolocation으로 위치를 받아오는데 기본 위치의 좌표값을 초기값으로 설정해두어서, 처음에 기본 위치의 데이터의 get 요청이 보내지고 현 위치의 좌표값이 업데이트 되면 get 요청이 다시 바뀐 좌표값으로 보내지게 된다.
이렇게 되면서 처음 받아온 1부터 10까지의 데이터와 두번째 받아온 데이터부터 중복된 값이 보이기 시작했다.

시도한 방법

배열로 이루어진 데이터를 고차함수 reduce를 사용해서 중복된 데이터를 제거하고 중복된 데이터를 제거한 것을 다시 map으로 렌더링을 할 수 있게끔 로직을 수정해주었다.

  const reduceShops = data.reduce((acc, shop) => {
    if (!acc.find((item) => item.hairShopId === shop.hairShopId)) {
      acc.push(shop);
    }
    return acc;
  }, []);

하지만 또 하나의 문제점이 있었다. 무한스크롤 훅에서는 위치정보가 바뀔 때 1 page의 첫번째 업체의 주소를 맨 위에 띄워주게 작성해놓았는데, 위치는 바뀌었지만 첫번째 데이터는 여전히 처음 받아온 기본값의 데이터였다.

 .then((res) => {
   setData((prevData) => [...prevData, ...res.data.data]);
   setHasMore(res.data.data.length > 0);
    if (res.data.pageInfo.page === 1) {
     const words = res.data.data[0].hairShopAddress.split(' ');
     dispatch(setAddress(`${words[1]} ${words[2]}`));
   }
})

해결 방법

무한스크롤 훅에서 get으로 받아온 데이터를 상태로 관리하고 있는데 useEffect로 좌표값이 바뀌게 되면 기존에 받아온 데이터를 다시 초기값인 빈 배열로 돌려놓는 로직을 추가했다. 이렇게 되면 위의 reduce로 중복 데이터를 제거할 필요도 없고, 좌표가 바뀐 채로 두번 요청이 있어도 이전에 받아온 데이터를 리셋하기 때문에 중복 데이터가 발생하지 않는다.

  useEffect(() => {
    setData([]);
  }, [lat, lng]);

2-2. useLocation 사용하기

마이페이지는 아래와 같은 구성으로 라우트 경로가 설정되어있다. index는 Mypage 라우트 안에 있는 기본 페이지를 설정하는 라우트를 정의한다. index 키워드는 기본 페이지를 나타내며, MyInfo 컴포넌트를 렌더링하도록 설정되어 있다. 따라서 Mypage 경로로 접근할 경우, MyInfo 컴포넌트가 기본 페이지로 표시된다.

<Route path={MYPAGE} element={<Mypage />}>
	<Route index element={<MyInfo />} />
   	<Route path={MYINFO} element={<MyInfo />} />
  	<Route path={MYRESERVE} element={<Myreserve />} />
    <Route path={MYREVIEW} element={<Myreview />}>
</Route>

마이페이지의 사이드 바에는 NavLink로 각각의 컴포넌트가 연결되게끔 구성되어져 있다. 이때, 마이페이지에 진입하면 기본 페이지가 MyInfo이므로 나의 정보라는 탭이 활성화 되어있는 CSS를 적용하고자 했다.

시도한 방법

NavLink의 active 클래스를 활용해서 페이지가 활성화 되어있는 경우에는 해당 CSS가 적용되게 했었다. 하지만 나의 정보 탭을 직접 누를 때만 CSS가 적용이 되고 처음 마이페이지에 진입했을 때는 나의 정보 탭은 기본 CSS가 적용이 되었다.

export const SideNav = styled(NavLink)`
  text-decoration: none;
  color: #333;
  &.active {
    color: cornflowerblue;
  }
`;

해결 방법

NavLink의 to 속성에 MYINFO 대신 MYPAGE를 연결하니 어떤 탭을 눌러도 나의 정보 탭이 활성화 된 CSS가 적용되었다.
그래서 path에 따라 우선 MYPAGE일 때는 스타일을 적용시킬 상태를 만들어 true 값을 주고, MYINFO를 제외한 다른 탭을 눌렀을 때는 상태를 false를 만들어 주고자 useLocation을 사용했다.
useLocation은 현재 URL 정보를 가져오는 훅으로, 객체로 이루어져 있다.
객체 안에는 hash, pathname, search, state가 있는데 이중에 pathname을 사용하면 내가 원하는 path일 때 조건을 작성할 수 있다.

  const location = useLocation();
  const [selected, setSelected] = useState(false);
  
  useEffect(() => {
    if (location.pathname === `${MYPAGE}`) {
      setSelected(true);
    } else {
      setSelected(false);
    }
  }, [location]);

  const handleClick = () => {
    setSelected(false);
  };

// 코드 생략
<S.SideNav to={MYINFO} className={selected ? 'active' : ''}> 
  나의 정보
</S.SideNav>
// 코드 생략
 <S.SideNav to={MYRESERVE} onClick={handleClick}>
  예약 관리
</S.SideNav>
profile
FrontEnd Developer

0개의 댓글