이번 프로젝트에서 게시글을 사용자가 선택한 옵션에 맞게 필터링 해 주는 기능을 만들어야 한다.
대부분의 사이트들이 선택한 필터링 조건을 url에 쿼리 스트링 형식으로 나타낸다. 그렇기에 새로고침이나 뒤로가기 등의 동작에도 사용자의 선택을 유지 시킬 수 있다.
우리 프로젝트는 기본적으로 url에 따라 보여줄 페이지를 매칭 시켜주는 리액트 라우터 라이브러리를 사용하고 있다.
리액트 라우터 라이브러리를 통해서 필터링 조건을 url로 설정하고, 쿼리를 파싱 하는 예제를 알아보자.
예제 동작 살펴보기
피자 주문을 위한 옵션 선택 창이다.
/ 도메인으로 최초 접속시 기본 form이 나온다.
페퍼로니, 피망, 올리브는 중복 선택이 가능하고, 크러스트는 세가지중 한가지만 가능하다. 소스 추가는 선택이다.
여기에서 옵션을 변경하면 다음과 같이 url에 쿼리로 옵션을 나타낸다.
선택한 옵션들이 쿼리스트링 형태로 url에 나타난다.
해당 url을 json형태로 파싱한 결과가 아래에 나타난다.
url에 따라 파싱 결과가 달라진다.
파싱한 내용을 바로 서버로 전송하여 조건에 맞는 검색 결과를 요청할 수 있다.
이와 같이 query string이 변경될 때 마다 원하는 형태로 파싱하도록 한다.
코드
커스텀 훅 useQueryParam 만들기
리액트 라우터에서 제공하는 useSearchParams
를 사용하여 옵션 선택을 쿼리 스트링으로 만들어 url에 설정하고, 변경된 url을 json형태로 파싱하는 커스텀 훅을 만든다.
현재 key에 대한 쿼리 스트링값과 쿼리 스트링을 새롭게 설정하는 함수를 반환하는 커스텀 훅이다.
function useQueryParam<T>(
key: string
): [T | undefined, (newQuery: T, options?: NavigateOptions) => void] {
let [searchParams, setSearchParams] = useSearchParams();
let paramValue = searchParams.get(key);
let value = React.useMemo(() => JSURL.parse(paramValue), [paramValue]);
// console.log(searchParams)
let setValue = React.useCallback(
(newValue: T, options?: NavigateOptions) => {
let newSearchParams = new URLSearchParams(searchParams);
newSearchParams.set(key, JSURL.stringify(newValue));
setSearchParams(newSearchParams, options);
},
[key, searchParams, setSearchParams]
);
return [value, setValue];
}
let paramValue = searchParams.get(key)
: url에서 key에 해당하는 쿼리 스트링을 가져온다.(jsurl 형식-라이브러리 설치 필요)
let value = React.useMemo(() => JSURL.parse(paramValue), [paramValue])
: paramValue
가 변경될 때 마다 jsurl형식을 json 형태로 파싱한다.
새로운 옵션을 url에 나타내기 위한 setValue
함수를 만든다.newValue
을 인자로 받아서 jsurl 형태로 변환 후 url에 설정한 새로운 URLSearchParams을 searchParams로 변경한다.
이 searchParams를 통해서 key에 대한 새로운 값을 searchParams.key
로 가져올 수 있다.
let setValue = React.useCallback(
(newValue: T, options?: NavigateOptions) => {
let newSearchParams = new URLSearchParams(searchParams);
newSearchParams.set(key, JSURL.stringify(newValue));
setSearchParams(newSearchParams, options);
},
[key, searchParams, setSearchParams]
);
커스텀훅 사용하기
옵션들이 변경되면 변경된 옵션을 url에 반영하기 위해서 우리가 만든 커스텀 훅을 사용한다. form의 양식이 변경 될 때 마다 해당 과정이 일어날 수 있도록 폼 변경 핸들러를 만든다.
function handleChange(event: React.ChangeEvent<HTMLFormElement>) {
let form = event.currentTarget;
let formData = new FormData(form);
let pizza: Pizza = {
toppings: formData.getAll("toppings") as string[],
crust: formData.get("crust") as string,
extraSauce: formData.get("extraSauce") === "on",
};
setPizza(pizza, { replace: false }); // replace:false를 하면 뒤로가기 했을 때 이전의 옵션 선택값이 나온다.
}
해당 핸들러를 각 폼 인풋에 연결 해 주면된다.
그동안 리액트 라우터를 사용할 때 기본적인 navigate, useParam정도의 api만 사용했는데 쿼리도 쉽게 가져올 수 있는 api가 있는 것을 알게 되었다!
이번 프로젝트에서는 타입스크립트를 도입하기로 했는데 이 예제를 보면서 제네릭의 활용 예제도 잘 볼 수 있어서 좋았다.