state를 적용한 url 업데이트 지연(해결완료)
✒️ 2025-05-28 10:33 내용 수정
- 오류 상황 : state를 url에 담아 처리하는 정렬 기능과 필터 기능을 만들었다. 필터 기능은 state 변경 및
useNavigate()후에 url이 최근 state로 잘 적용되었다. 하지만 정렬 기능은 url이 변경 전 state를 적용하여 생성되어 실제 화면과 url이 일치하지 않았다. - 오류 사진
- 버튼은 마우스를 올려 놓으면 "가격 내림차순 보기"로 뜬다.(현재 상태의 반대로 이동하기 역할)
작성 코드 일부
- 정렬을 관리하는
orderstate와filterstate를 사용했고, 적용된 옵션의 url을 생성하는 함수handleOptionClick을 설정했다.
const [order, setOrder] = useState({ // 정렬기준
name : searchParams.get("order") ?? 'createdAt',
ascend : searchParams.get("ascend") ?? false
});
const [filter, setFilter] = useState({ // 필터링
sold : (!searchParams.get("sold") || searchParams.get("sold") === 'null') ? null : searchParams.get("sold"),
category_id : searchParams.get("category_id") ?? 0
});
const navigate = useNavigate();
function handleOptionClick() { // 필터, 정렬 적용
navigate(`/user/${targetUserId}/product?sold=${filter.sold}&category_id=${filter.category_id}&order=${order.name}&ascend=${order.ascend}`);
}
- 정렬 Component에서
onClick으로 버튼 클릭 시 state를 변경하고,navigate()를 수행한다.
function handleSort(e) { // 정렬 처리
let order_id = e.currentTarget.id;
setOrder((order)=>({...order, name : order_id, ascend : !typeAscend}));
// 문제 -- url이 이전 state로 생성되어 현재 state와 차이가 있음
handleOptionClick();
}
- 필터 Component에서
input checkbox를 사용해서onChange으로 state를 변경하고,onClick으로navigate()를 수행한다.
function handleFilterBtn(targetIdName) {
if (targetIdName === 'reset_filter') {
setFilter((filter)=>({...filter, sold : null, category_id : 0}));
setCurrentCategory(-1);
return;
}
handleOptionClick(); // 이동처리
}
function handleCategoryChange(event, index, category_id) { // 카테고리 선택 수정
if (!index && !category_id) {
setFilter((filter)=>({...filter, sold : filter.sold}));
} else {
if (event.target.checked) {
setFilter((filter)=>({...filter, category_id : category_id}));
setCurrentCategory(index);
}
}
}
- 재 렌더링은
useEffect()로, 부모 Component에서searchParams가 변경되거나,order와filter하고 관계 없는 기타 state가 바뀔 때 렌더링 되도록 설정했다. - 정렬과 필터 둘 다 state를 바꾸고
navigate()하는 것은 동일하지만, 필터는 새로 수정된 state로 작성된 url로 이동하고, 정렬은 이전 state로 작성된 url로 이동했다.
시도했던 해결 방법
- 정렬 Component에서
useEffect()로orderstate가 변경될 때마다handleOptionClick()를 호출하면 url과 렌더링 된 화면의 데이터가 일치한다.- 가장 정석적인 해결 방법이다.
- 하지만 정렬과 같은 부모 Component의 자식인 pagination Component도 url을 기반으로 렌더링이 되도록 설정해서 order에 새 값을 지정하지 않았음에도 다른 페이지로 넘어가는 기능이 작동하지 않았다.
- 페이징 처리를 위해 이 방법을 사용할 수 없었다.
- 필터처럼 특정 버튼을 눌러야
navigate()수행하도록 처리한다.- 이 방법을 썼을 때 url에 변경된 state가 설정되어 있었다.
- 하지만 사용자가 정렬 버튼을 누르고 적용 버튼을 눌러야 하는 번거로움이 있다. 보통 정렬 기능은 정렬 버튼을 1번만 눌러도 수행되었기에 이 역시 마음에 들지 않았다.
useMemo()로order와filter를 설정해준다.- 해결에 큰 도움이 되지 않았다.
- pagination에서
searchParam.get("page")로 의존성을 더 명확하게 설정한다.- 정렬의
order의존에 의한useEffect()때문에 도움이 되지 않았다.
- 정렬의
- 해결한 방법
navigate()에서 url에order를order.name이 아닌 새로 바꿀 값order_id로 지정했다.- state의 초기값 및 렌더링 후 값 처리가 url에 있는 query string을 기반으로 설계했었다.
- 처음부터 이동할 url에 넘겨줄 값을 새로 바꿀 값으로 대체하면 해결될 문제였다..
- 페이지 처리에도 영향이 없고 정렬 버튼을 누르면 새 url로 잘 변경된다.
- 다만 설정 환경에 따라 1번 방법이 더 정확할 수 있다.
- state의 초기값 및 렌더링 후 값 처리가 url에 있는 query string을 기반으로 설계했었다.
function handleSort(e) { // 정렬 처리
let order_id = e.currentTarget.id;
setOrder((order)=>({...order, name : order_id, ascend : !typeAscend}));
// 이동할 url의 order와 ascend 부분에 아예 새로 바꿀 값을 넣어준다.
navigate(`/user/${targetUserId}/product?sold=${filter.sold}&category_id=${filter.category_id}&order=${order_id}&ascend=${!typeAscend}`);
}
- 데이터, url, 렌더링 후 출력된 로그 모두 일치한다.
- 버튼은 마우스를 올려 놓으면 "가격 내림차순 보기"로 뜬다.(현재 상태의 반대로 이동하기 역할)
- 버튼은 마우스를 올려 놓으면 "가격 내림차순 보기"로 뜬다.(현재 상태의 반대로 이동하기 역할)
결론
- 정렬과 필터가 같은 방식으로 동작함에도 불구하고 state를 적용한 url 처리가 다르게 발생했다.
- 페이지 처리 기능으로 인해
useEffect()의존성 설정과 재 렌더링 처리에 제약이 발생해서 정석적인 해결 방법을 사용할 수 없었다. 정렬 기능 사용 시의 데이터 출력 내용과 url을 일치할 수 있는 방법을 더 찾아볼 예정이다.- state를 url의 query string(
searchParams)로 초기값과 변화를 설정했기에 이동할 url 값에 미리 값을 할당해서 새로 렌더링 된 화면에서 의도한 state를 설정할 수 있었다.