오늘은 필터 기능 작업을 했다.
Dropdown 으로 구성된 여러가지 필터들과 검색창이 있고, 필터 옵션이 추가/제거/변경될 때 마다 그에 맞는 옵션들을 쿼리에 담아 api 요청을 해야 한다.
여러 필터들이 있고 구조는 이러하다.
const initialFilter: FilterOptions = {
date: "",
queryText: "",
department: "",
manager : "",
status: "",
offset: 0,
currentPage: 1,
startDate: "",
endDate: "",
};
const [filterOption, setFilterOption] = useState<FilterOptions>(
initialFilter
);
(...)
useEffect(()=>{
dispatch(getAppointmentList({...filterOption}))
},[filterOption])
처음 코드를 작성할 때에는 filterOption.department, filterOption.manager 와 같이 구분 없이 그냥 filterOption 을 useEffect 의 두 번째 인자로 전달했다.
그렇게 되면 처음 컴포넌트가 마운트 될 때와 filterOption 이 update 될 때 액션이 dispatch 되었다.
하지만 filterOption 을 destructuring 하도록 코드리뷰를 받고 이를 수정했다.
useEffect(()=>{
dispatch(getAppointmentList({...filterOption}))
},[filterOption.manager])
useEffect(()=>{
dispatch(getAppointmentList({...filterOption}))
},[filterOption.department])
하지만 이렇게 코드를 수정하고 나니 당연하게도 컴포넌트가 최초로 마운트 될 때 쓸데없이 같은 액션이 여러 번 dispatch 되는 것을 확인했다. 마운트될 때에는 dispatch를 하지 않고 filterOption.department가 업데이트 될 때에만 액션을 dispatch 하고 싶었고, 이럴 때에는 useRef 을 사용하면 된다.
useEffect는 위에서부터 아래로 차례대로 적용되므로 옵션이 여러개라면 마지막에 firstRender.current=false 로 바꾸어주면 마운트 될 때를 건너띄고 update 될 때에만 적용이 되게 된다.
const firstRender = useRef(true);
useEffect(()=>{
if(firstRender.current){
return
} else {
dispatch(getAppointmentList({...filterOption}))
}
},[filterOption.manager])
useEffect(()=>{
if(firstRender.current){
firstRender.current = false;
return
} else {
dispatch(getAppointmentList({...filterOption}))
}
},[filterOption.department])
출처 스택오버플로우 : Make React useEffect hook not run on initial render